如果不使用子进程,如何使用python读取stderr?

约翰

我正在使用cwiid库,该库是用C编写的,但在python中使用。该库使我可以使用Wiimote来控制机器人上的某些电机。该代码在没有监视器,键盘或鼠标的嵌入式设备上作为守护程序运行。

当我尝试初始化对象时:

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()以查看是否出现消息“套接字连接错误(控制通道)”,如果出现,则重新启动。

到目前为止,我可以使用一些os.dup()os.dup2()方法重定向stderr以防止显示该消息,但这似乎并不能帮助我阅读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

不过,这似乎并没有按照我认为的方式工作。

卡尔·布尔

subprocess幕后,除了使用dups外,还使用匿名管道来重定向子流程输出。要使进程读取其自己的stderr,您需要手动执行此操作。它涉及获取匿名管道,将标准错误重定向到管道的输入,运行有问题的stderr写入操作,从管道另一端读取输出以及清理所有备份。一切都很轻松,但是我认为我在下面的代码中做到了。

您的cwiid.Wiimote调用的以下包装器将返回一个元组,该元组由函数调用返回的结果(None如果为RuntimeError)和生成的stderr输出(如果有)组成。有关tests在各种条件下应如何工作的示例,请参见该函数。我在适应您的示例循环时遇到了麻烦,但是不太了解cwiid.Wiimote调用成功后会发生什么在示例代码中,您只是立即重新循环。

编辑:糟糕!修复了在example_loop()哪里Wiimote调用而不是作为参数传递的错误。

import time

import os
import fcntl

def capture_runtime_stderr(action):
    """Handle runtime errors and capture stderr"""
    (r,w) = os.pipe()
    fcntl.fcntl(w, fcntl.F_SETFL, os.O_NONBLOCK)
    saved_stderr = os.dup(2)
    os.dup2(w, 2)
    try:
        result = action()
    except RuntimeError:
        result = None
    finally:
        os.close(w)
        os.dup2(saved_stderr, 2)
        with os.fdopen(r) as o:
            output = o.read()
    return (result, output)

## some tests

def return_value():
    return 5

def return_value_with_stderr():
    os.system("echo >&2 some output")
    return 10

def runtime_error():
    os.system("echo >&2 runtime error occurred")
    raise RuntimeError()

def tests():
    print(capture_runtime_stderr(return_value))
    print(capture_runtime_stderr(return_value_with_stderr))
    print(capture_runtime_stderr(runtime_error))
    os.system("echo >&2 never fear, stderr is back to normal")

## possible code for your loop

def example_loop():
    while True:
        (wm, output) = capture_runtime_stderr(cmiid.Wiimote)
        if wm == None:
            if "Socket connect error" in output:
                raise RuntimeError("library borked, time to reboot")
            time.sleep(1)
            continue
        ## do something with wm??

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何使用子进程Popen读取stdout和stderr并将其全部保存?

来自分类Dev

如何在不使用shell = True的情况下执行此Python子进程调用?

来自分类Dev

使用子进程读取输入?

来自分类Dev

如果创建,Python子进程stderr / stdout字段为None

来自分类Dev

如何使用自定义的类文件对象作为子进程stdout / stderr?

来自分类Dev

如果失败则如何退出python子进程

来自分类Dev

使用stdout / stderr以外的管道与子进程进行通信

来自分类Dev

使用crontab的Python子进程

来自分类Dev

不使用shell选项无法从python子进程调用ubuntu'ulimit'

来自分类Dev

如果不使用PHP语句,如何使用AND / OR

来自分类Dev

如果不使用函数,则SQL或子查询(如果可能)

来自分类Dev

使用python multiprocessing子进程如何终止另一个子进程?

来自分类Dev

如何使用子进程强制python释放内存?

来自分类Dev

如何使Maven与Python子进程一起使用?

来自分类Dev

如何使用python子进程运行Rabbitmqctl命令?

来自分类Dev

如何在Python中使用正确的子进程Pclose?

来自分类Dev

如何在Python和子进程中使用套接字?

来自分类Dev

如何使用python通过子进程与Excel文件通信?

来自分类Dev

Python子进程抑制stdout和stderr

来自分类Dev

如何分配ID,如果不使用则删除

来自分类Dev

使用 Python 的子进程读取通过 stdin 发送的阻塞命令的输出

来自分类Dev

如果不使用python Pandas中的datetime

来自分类Dev

使用Python立即启动Python子进程

来自分类Dev

使用Python立即启动Python子进程

来自分类Dev

如何在不使用阻塞stdio的情况下从node.js的子进程传输大数据/向子进程传输大数据?

来自分类Dev

如果不使用 mongoengine (python),我如何更新如果存在和插入

来自分类Dev

在不使用管道的情况下读取子流程的输出

来自分类Dev

使用python的子进程模块打开python进程

来自分类Dev

如何在不使用临时文件的情况下在子进程中实现延迟的stdout?

Related 相关文章

  1. 1

    如何使用子进程Popen读取stdout和stderr并将其全部保存?

  2. 2

    如何在不使用shell = True的情况下执行此Python子进程调用?

  3. 3

    使用子进程读取输入?

  4. 4

    如果创建,Python子进程stderr / stdout字段为None

  5. 5

    如何使用自定义的类文件对象作为子进程stdout / stderr?

  6. 6

    如果失败则如何退出python子进程

  7. 7

    使用stdout / stderr以外的管道与子进程进行通信

  8. 8

    使用crontab的Python子进程

  9. 9

    不使用shell选项无法从python子进程调用ubuntu'ulimit'

  10. 10

    如果不使用PHP语句,如何使用AND / OR

  11. 11

    如果不使用函数,则SQL或子查询(如果可能)

  12. 12

    使用python multiprocessing子进程如何终止另一个子进程?

  13. 13

    如何使用子进程强制python释放内存?

  14. 14

    如何使Maven与Python子进程一起使用?

  15. 15

    如何使用python子进程运行Rabbitmqctl命令?

  16. 16

    如何在Python中使用正确的子进程Pclose?

  17. 17

    如何在Python和子进程中使用套接字?

  18. 18

    如何使用python通过子进程与Excel文件通信?

  19. 19

    Python子进程抑制stdout和stderr

  20. 20

    如何分配ID,如果不使用则删除

  21. 21

    使用 Python 的子进程读取通过 stdin 发送的阻塞命令的输出

  22. 22

    如果不使用python Pandas中的datetime

  23. 23

    使用Python立即启动Python子进程

  24. 24

    使用Python立即启动Python子进程

  25. 25

    如何在不使用阻塞stdio的情况下从node.js的子进程传输大数据/向子进程传输大数据?

  26. 26

    如果不使用 mongoengine (python),我如何更新如果存在和插入

  27. 27

    在不使用管道的情况下读取子流程的输出

  28. 28

    使用python的子进程模块打开python进程

  29. 29

    如何在不使用临时文件的情况下在子进程中实现延迟的stdout?

热门标签

归档