【问题标题】:Run subprocess inside Python thread reading the output in realtime在 Python 线程中运行子进程,实时读取输出
【发布时间】:2015-08-06 20:31:04
【问题描述】:

考虑以下 Python 代码:

import io
import time
import subprocess
import sys

from thread import start_new_thread

def ping_function(ip):

    filename = 'file.log'
    command = ["ping", ip]

    with io.open(filename, 'wb') as writer, io.open(filename, 'rb', 1) as reader:
        process = subprocess.Popen(command, stdout=writer)
        while process.poll() is None:
            line = reader.read()
            # Do something with line
            sys.stdout.write(line)
            time.sleep(0.5)
        # Read the remaining
        sys.stdout.write(reader.read())

ping_function("google.com")

目标是运行一个 shell 命令(在本例中为 ping,但此处不相关)并实时处理输出,该输出也保存在日志文件中。

换句话说,ping 是在后台运行的,它每秒都会在终端上产生输出。我的代码将读取此输出(每 0.5 秒),对其进行解析并(几乎)实时执行一些操作。

这里的实时意味着我不想等待进程结束来读取输出。在这种情况下,实际上 ping 永远不会完成,因此我刚才描述的方法是强制性的。

我已经测试了上面的代码,它实际上可以正常工作:)

现在我想在一个单独的线程中调整它,所以我将最后一行替换为以下内容:

from thread import start_new_thread
start_new_thread(ping_function, ("google.com", ))

由于某种原因,这不再起作用,并且阅读器总是返回空字符串。 特别是 reader.read() 返回的字符串总是空的。

使用队列或其他全局变量无济于事,因为我什至在首先检索数据时遇到问题(即获取 shell 命令的输出)

我的问题是:

  • 我该如何解释这种行为?

  • 在单独的线程中运行进程是个好主意还是我应该使用不同的方法? This article 表示不是……

  • 如何修复代码?

谢谢!

【问题讨论】:

    标签: python multithreading process


    【解决方案1】:

    你不应该在启动线程后分叉。您可以在启动 fork 后进行线程处理,因此您可以让线程处理 I/O 管道,但是...

    让我重复一遍:你不应该在启动线程后分叉

    那篇文章解释得很好。一旦启动线程,您就无法控制程序的状态。尤其是在后台运行的 Python 中。

    要修复您的代码,只需从主线程启动子进程,然后启动线程。在一个线程中处理来自管道的 I/O 是完全可以的。

    【讨论】:

    • 这很有意义。感谢您的回答
    猜你喜欢
    • 2012-04-06
    • 2016-08-20
    • 2013-01-25
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 2015-06-08
    相关资源
    最近更新 更多