【问题标题】:Way to prevent stdout.readline() from freezing program防止 stdout.readline() 冻结程序的方法
【发布时间】:2021-07-25 22:59:10
【问题描述】:

在我当前的程序中,我使用 subprocess.Popen() 启动服务器并使用 readline() 继续从标准输出读取。但是,当它卡在 readline 上时,直到出现新行。这很糟糕,因为我需要能够在等待服务器输出时执行其他代码。有没有办法阻止这种情况发生?

import subprocess

server = subprocess.Popen("startup command", stdout= subprocess.PIPE, encoding= "utf-8")

while True:
    out = server.stdout.readline()
    if out != "":
        print(out)
    print("checked for line")

我宁愿避免使用多线程,因为我的代码的不同部分将不再是线程安全的。

【问题讨论】:

  • 你必须使用线程。由于 GIL,线程安全在 Python 中通常不是大问题。
  • 取决于你在做什么。您仍然可以与 GIL 交错。设置threading.Queue 非常简单,可以轻松沟通。
  • 绝对没有理由让线程参与进来;此时它们只会使您的程序复杂化。如果简单地轮询不是一个合理的选择,请使用其中一个异步库(有几个,而且在所有这些库中都很容易)。请记住,通过管道传输到子进程的文件描述符实际上与任何其他文件描述符没有什么不同;对其进行特殊处理的唯一原因是您还可以在需要时跟踪退出代码。

标签: python subprocess popen


【解决方案1】:

正如@tim Roberts 所说,您将要使用线程。您需要做的是让您的读取循环将事件发布到主线程。无论是使用全局标志还是队列。查看队列的文档。

https://docs.python.org/3/library/queue.html

【讨论】:

    【解决方案2】:

    改用poll()communicate()

    import subprocess
    import time
    
    with subprocess.Popen(['bash', '-c', 'sleep 1 && echo OK'], stdout=subprocess.PIPE) as proc:
        while proc.poll() is None:
            print('<doing something useful>')
            time.sleep(0.3)
        out, err = proc.communicate()
        print(out)
    
    <doing something useful>
    <doing something useful>
    <doing something useful>
    <doing something useful>
    b'OK\n'
    

    【讨论】:

    • 我认为这不会帮助解决 OP 的问题,因为听起来他们想将阅读和工作交错。记住Popen.poll 不是普通的文件描述符poll
    • TBH,整个问题只需要reading asyncio documentation¯\_(ツ)_/¯
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    相关资源
    最近更新 更多