boo*_*ull 4 python multithreading subprocess stdout python-3.x
如果需要定期检查stdout正在运行的进程.例如,进程是tail -f /tmp/file在python脚本中生成的.然后每隔x秒,该子进程的stdout被写入字符串并进一步处理.脚本最终会停止子进程.
解析子check_output进程的stdout,如果直到现在使用,这似乎不起作用,因为进程仍在运行并且不会产生确定的输出.
>>> from subprocess import check_output
>>> out = check_output(["tail", "-f", "/tmp/file"])
#(waiting for tail to finish)
Run Code Online (Sandbox Code Playgroud)
应该可以为子进程使用线程,以便可以处理多个子进程的输出(例如tail -f/tmp/file1,tail -f/tmp/file2).
如何启动子进程,定期检查和处理其标准输出并最终以多线程友好的方式停止子进程?python脚本在Linux系统上运行.
目标不是连续读取文件,tail命令是一个示例,因为它的行为与使用的实际命令完全相同.
编辑:我没想到这个,文件不存在.check_output现在只需等待该过程完成.
edit2:一种替代方法,使用Popen并且PIPE似乎导致相同的问题.它等待tail完成.
>>> from subprocess import Popen, PIPE, STDOUT
>>> cmd = 'tail -f /tmp/file'
>>> p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
>>> output = p.stdout.read()
#(waiting for tail to finish)
Run Code Online (Sandbox Code Playgroud)
你的第二次尝试是正确的90%.唯一的问题是,你试图读取所有的tail在同一时间,一旦它完成的标准输出.但是,tail打算在后台运行(无限期?),所以你真的想逐行读取stdout:
from subprocess import Popen, PIPE, STDOUT
p = Popen(["tail", "-f", "/tmp/file"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
for line in p.stdout:
print(line)
Run Code Online (Sandbox Code Playgroud)
我删除了shell=True和close_fds=True参数.第一个是不必要的,有潜在危险,而第二个是默认值.
请记住,文件对象可以在Python中通过它们的行进行迭代.该for循环将持续到tail管芯,但因为它出现它将处理每一行,而不是read,这将阻塞,直到tail模具.
如果我创建一个空文件/tmp/file,启动该程序并开始使用另一个shell将行回显到文件中,程序将回显这些行.您可能应该print用更有用的东西替换.
以下是我在启动上述代码后输入的命令示例:
命令行
$ echo a > /tmp/file
$ echo b > /tmp/file
$ echo c >> /tmp/file
Run Code Online (Sandbox Code Playgroud)
程序输出(来自不同shell中的Python)
b'a\n'
b'tail: /tmp/file: file truncated\n'
b'b\n'
b'c\n'
Run Code Online (Sandbox Code Playgroud)
如果您希望主程序在响应输出时响应tail,请在单独的线程中启动循环.您应该将此线程设置为守护程序,以便即使tail未完成也不会阻止程序退出.您可以让线程打开子流程,也可以将标准输出传递给它.我更喜欢后一种方法,因为它可以让你在主线程中有更多的控制权:
def deal_with_stdout():
for line in p.stdout:
print(line)
from subprocess import Popen, PIPE, STDOUT
from threading import Thread
p = Popen(["tail", "-f", "/tmp/file"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
t = Thread(target=deal_with_stdout, daemon=True)
t.start()
t.join()
Run Code Online (Sandbox Code Playgroud)
这里的代码几乎相同,添加了一个新线程.我join()在最后添加了一个,所以程序会表现得很好(join等待线程在返回之前死掉).您可能希望用通常运行的任何处理代码替换它.
如果您的线程足够复杂,您可能还希望继承Thread并覆盖该run方法,而不是传入一个简单的方法target.
| 归档时间: |
|
| 查看次数: |
3787 次 |
| 最近记录: |