Я работаю с библиотекой cwiid, которая является библиотекой, написанной на C, но используется в python. Библиотека позволяет мне использовать Wiimote для управления некоторыми двигателями на роботе. Код работает как демон на встроенном устройстве без монитора, клавиатуры или мыши.Как я могу прочитать stderr с python, если я НЕ использую подпроцесс?
Когда я пытаюсь инициализировать объект:
import cwiid
while True:
try:
wm = cwiid.Wiimote()
except RuntimeError:
# RuntimeError exception thrown if no Wiimote is trying to connect
# Wait a second
time.sleep(1)
# Try again
continue
99% времени, все работает, но один раз в то время, библиотека получает в какой-то странное состояние, в котором вызов cwiid.Wiimote()
результатов в запись в библиотеке «Ошибка подключения сокета (канал управления)» на stderr и python, бросающий исключение. Когда это происходит, каждый последующий вызов cwiid.Wiimote()
приводит к тому, что то же самое записывается в stderr, и при этом возникает одно и то же исключение, пока я не перезагружу устройство.
Что я хочу сделать, это обнаружить эту проблему и перезагрузить устройство python автоматически.
Тип исключения, создаваемый библиотекой cwiid, если он находится в странном состоянии, также является RuntimeError
, который не отличается от исключения тайм-аута соединения (что очень часто встречается), поэтому я не могу отличить его таким образом. То, что я хочу сделать, это прочитать stderr сразу после запуска cwiid.Wiimote()
, чтобы узнать, появляется ли сообщение «Ошибка подключения сокета (канал управления)». появляется, и если да, перезагрузитесь.
До сих пор я мог перенаправить stderr, чтобы предотвратить появление сообщения, используя некоторые методы и os.dup2()
, но это, похоже, не помогает мне читать stderr.
Большинство примеров онлайн сделок с чтением stderr, если вы используете что-то с подпроцессом, который в этом случае не применяется.
Как я могу прочитать чтение stderr, чтобы обнаружить сообщение, написанное на нем?
Я думаю, что я ищу что-то вроде:
while True:
try:
r, w = os.pipe()
os.dup2(sys.stderr.fileno(), r)
wm = cwiid.Wiimote()
except RuntimeError:
# RuntimeError exception thrown if no Wiimote is trying to connect
if ('Socket connect error (control channel)' in os.read(r, 100)):
# Reboot
# Wait a second
time.sleep(1)
# Try again
continue
Это, кажется, не работает так, как я думаю, он должен хотя.
Зачастую появляется сообщение об ошибке с исключением. Вы можете выполнить 'except RuntimeError как e:', а затем прочитать сообщение об ошибке с помощью 'str (e)' и реагировать по-разному в зависимости от сообщения. – SethMMorton
После просмотра кода библиотеки на github вам может быть не повезло. Как сейчас, конкретные ошибки соединения, такие как те, которые вы сообщаете, печатаются только на 'stderr', а затем объединены в единый' RuntimeError' с строкой сообщения '' Ошибка открытия соединения wiimote''. То, что говорит SethMMorton, действительно, но вы, вероятно, не найдете строку stderr. По крайней мере, пока. В соответствии с исходным вопросом, перехватывая 'stderr' другого процесса, это может быть слишком много, но стоит проверить: http://github.com/jerome-pouiller/reredirect Удачи. – sal
Хорошо, я могу показать вам, как перенаправить stderr внутри процесса так, как вы хотите, но можете ли вы прояснить что-то в своем примере цикла: что вы вообще делаете с 'wm'? Похоже, что если вызов cwiid.Wiimote() преуспевает, вы просто повторно зацикливаете сразу - нет 'break' от вашего' while True'. –