我试图通过定义自己的输出流来获得subprocess.call的实时输出,但它似乎不起作用。
原因:我想运行一个子进程,并将该调用输出到两个stdout(实时,以便我可以查看脚本并查看当前进度)以及将其记录到文件
subprocess.py:
> show dbs
Wed Sep 13 11:18:32.964 listDatabases failed:{ "ok" : 0, "errmsg" : "unauthorized" } at src/mongo/shell/mongo.js:46
>
mainprocess.py
import time
while True:
print("Things")
time.sleep(1)
但是当我运行此代码时,我收到此错误消息:
import subprocess
import io
class CustomIO(io.IOBase):
def write(self, str):
print("CustomIO: %s"%str)
# logging to be implemented here
customio = CustomIO()
subprocess.call(["python3", "print_process.py"], stdout=customio)
那么,任何人都有任何线索,如果可能的话?
我是否继承了错误的基类?
我没有超载正确的方法吗?
或者我完全脱离了轨道,应该以完全不同的方式解决这个问题?
答案 0 :(得分:2)
如果要处理子流程的输出,则需要传递stdout=subprocess.PIPE
。但是,call()
和run()
都会等到进程完成后再使其可用,因此您无法使用这些函数实时处理它。
您需要使用subprocess.Popen
:
import subprocess as sp
def handle_output(output_line):
...
my_process = sp.Popen(["python3", "print_process.py"],
stdout=sp.PIPE,
universal_newlines=True) # changes stdout from bytes to text
for line in my_process.stdout:
handle_output(line)
my_process.wait()
更新:确保在子进程中刷新输出缓冲区:
while True:
print("Things", flush=True)
time.sleep(1)
答案 1 :(得分:1)
您需要使用文件描述符指定和打开流。 fileno
未实现io.IOBase
,因为这只是一个内存中的流:
stdin
,stdout
和stderr
指定已执行程序的标准 输入,标准输出和标准错误文件句柄。 有效值为PIPE
,DEVNULL
,现有文件描述符(a 正整数),现有文件对象和None
。PIPE
表示 应该创建一个给孩子的新管道。DEVNULL
表示 将使用特殊文件os.devnull
。使用默认设置None
,不会发生重定向;
因此您可以将套接字,管道和打开文件用作stdout
,文件描述符将作为stdout传递给子进程。我没有使用subprocess.Popen
的套接字,但是我希望它们能够工作,我相信这里重要的是子文件的文件描述符,而不是文件描述符所指向的对象类型。