加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

检查python中正在运行的子进程的stdout

发布时间:2020-12-20 11:58:17 所属栏目:Python 来源:网络整理
导读:如果需要定期检查正在运行的进程的stdout.例如,进程是tail -f / tmp / file,它是在 python脚本中生成的.然后每隔x秒,该子进程的stdout被写入字符串并进一步处理.脚本最终会停止子进程. 要解析子进程的stdout,如果直到现在使用check_output,这似乎不起作用,因
如果需要定期检查正在运行的进程的stdout.例如,进程是tail -f / tmp / file,它是在 python脚本中生成的.然后每隔x秒,该子进程的stdout被写入字符串并进一步处理.脚本最终会停止子进程.

要解析子进程的stdout,如果直到现在使用check_output,这似乎不起作用,因为进程仍在运行并且不会产生确定的输出.

>>> from subprocess import check_output
>>> out = check_output(["tail","-f","/tmp/file"])
 #(waiting for tail to finish)

应该可以为子进程使用线程,以便可以处理多个子进程的输出(例如tail -f / tmp / file1,tail -f / tmp / file2).

如何启动子进程,定期检查和处理其标准输出并最终以多线程友好的方式停止子进程? python脚本在Linux系统上运行.

目标不是连续读取文件,tail命令是一个示例,因为它的行为与使用的实际命令完全相同.

编辑:我没想到这个,文件不存在. check_output现在只是等待进程完成.

edit2:另一种方法,使用Popen和PIPE似乎会导致同样的问题.它等待尾巴完成.

>>> 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)

解决方法

你的第二次尝试是正确的90%.唯一的问题是你试图在它完成后同时读取所有尾部的标准输出.但是,tail应该在后台运行(无限期?),所以你真的想逐行读取stdout:

from subprocess import Popen,STDOUT
p = Popen(["tail","/tmp/file"],stderr=STDOUT)
for line in p.stdout:
    print(line)

我删除了shell = True和close_fds = True参数.第一个是不必要的,有潜在危险,而第二个是默认值.

请记住,文件对象可以在Python中通过它们的行进行迭代. for循环将一直运行,直到尾部死亡,但它将处理每条线,而不是读取,这将阻塞直到尾部死亡.

如果我在/ tmp / file中创建一个空文件,启动该程序并开始使用另一个shell将行回显到文件中,程序将回显这些行.您可能应该用更有用的东西替换print.

以下是我在启动上述代码后输入的命令示例:

命令行

$echo a > /tmp/file
$echo b > /tmp/file
$echo c >> /tmp/file

程序输出(来自不同shell中的Python)

b'an'
b'tail: /tmp/file: file truncatedn'
b'bn'
b'cn'

如果您希望主程序在响应tail的输出时响应,请在单独的线程中启动循环.您应该将此线程设置为守护程序,以便即使尾部未完成也不会阻止程序退出.您可以让线程打开子流程,也可以将标准输出传递给它.我更喜欢后一种方法,因为它可以让你在主线程中有更多的控制权:

def deal_with_stdout():
    for line in p.stdout:
        print(line)

from subprocess import Popen,STDOUT
from threading import Thread
p = Popen(["tail",stderr=STDOUT)
t = Thread(target=deal_with_stdout,daemon=True)
t.start()
t.join()

这里的代码几乎相同,添加了一个新线程.我在最后添加了一个join(),所以程序作为一个例子表现得很好(join在返回之前等待线程死掉).您可能希望用通常运行的任何处理代码替换它.

如果您的线程足够复杂,您可能还希望从Thread继承并覆盖run方法而不是传入一个简单的目标.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读