[英]How does one create custom output stream for subprocess.call
I am trying to get realtime output of a subprocess.call by defining my own output stream but it doesn't seem to work. 我试图通过定义我自己的输出流来获得subprocess.call的实时输出,但它似乎不起作用。
Reason: I want to run a subprocess and get output of that call to both stdout(in realtime so i can look at the script and see current progress) as well as logging it to a file 原因:我想运行一个子进程并将该调用输出到两个stdout(实时,这样我可以查看脚本并查看当前进度)以及将其记录到文件中
subprocess.py: subprocess.py:
import time
while True:
print("Things")
time.sleep(1)
mainprocess.py mainprocess.py
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)
But when i run this code i get this error message: 但是,当我运行此代码时,我收到此错误消息:
Traceback (most recent call last):
File "call_test.py", line 9, in <module>
subprocess.call(["python3", "print_process.py"], stdout=customio)
File "/usr/lib/python3.4/subprocess.py", line 537, in call
with Popen(*popenargs, **kwargs) as p:
File "/usr/lib/python3.4/subprocess.py", line 823, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/usr/lib/python3.4/subprocess.py", line 1302, in _get_handles
c2pwrite = stdout.fileno()
io.UnsupportedOperation: fileno
So, anyone have any clue if this is possible? 那么,任何人都有任何线索,如果可能的话?
Am i inheriting the wrong baseclass? 我继承了错误的基类吗?
Am i not overloading the proper methods? 我没有超载正确的方法吗?
Or am i completely off the rails and should be going about this in a completely different way? 或者我完全脱离了轨道,应该以完全不同的方式解决这个问题?
If you want to process the output of a subprocess, you need to pass stdout=subprocess.PIPE
. 如果要处理子进程的输出,则需要传递stdout=subprocess.PIPE
。 However, call()
and run()
will both wait until the process is finished before making it available, so you cannot handle it in real time using these functions. 但是, call()
和run()
都会等到进程完成后再使其可用,因此您无法使用这些函数实时处理它。
You need to use subprocess.Popen
: 你需要使用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()
Update: Make sure to flush the output buffer in your child process: 更新:确保刷新子进程中的输出缓冲区:
while True:
print("Things", flush=True)
time.sleep(1)
You need to specify and open stream with a file descriptor. 您需要使用文件描述符指定和打开流。 fileno
isn't implemented for io.IOBase
because this is just an in-memory stream: fileno
没有为实现io.IOBase
,因为这仅仅是一个内存流:
Frequently Used Arguments 经常使用的参数
stdin
,stdout
andstderr
specify the executed program's standard input, standard output and standard error file handles, respectively.stdin
,stdout
和stderr
指定执行程序的标准输入,标准输出和标准错误文件句柄。 Valid values arePIPE
,DEVNULL
, an existing file descriptor (a positive integer), an existing file object, andNone
. 有效值为PIPE
,DEVNULL
,现有文件描述符(正整数),现有文件对象和None
。PIPE
indicates that a new pipe to the child should be created.PIPE
表示应该创建一个新的子管道。DEVNULL
indicates that the special fileos.devnull
will be used.DEVNULL
表示将使用特殊文件os.devnull
。 With the default settings ofNone
, no redirection will occur; 使用默认设置None
,不会发生重定向;
So you might use sockets, pipes, and open files as stdout
, the file descriptor is passed to the child process as it's stdout. 因此,您可以将套接字,管道和打开文件用作stdout
,文件描述符将作为stdout
传递给子进程。 I didn't use sockets with subprocess.Popen
though, but I expect them to work, I believe what matters here is the file descriptor to the child, not what type of object the file descriptor points to. 我没有使用带有subprocess.Popen
套接字,但是我希望它们可以工作,我相信这里重要的是子文件描述符,而不是文件描述符所指向的对象类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.