简体   繁体   English

如何为subprocess.call创建自定义输出流

[英]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 and stderr specify the executed program's standard input, standard output and standard error file handles, respectively. stdinstdoutstderr指定执行程序的标准输入,标准输出和标准错误文件句柄。 Valid values are PIPE , DEVNULL , an existing file descriptor (a positive integer), an existing file object, and None . 有效值为PIPEDEVNULL ,现有文件描述符(正整数),现有文件对象和None PIPE indicates that a new pipe to the child should be created. PIPE表示应该创建一个新的子管道。 DEVNULL indicates that the special file os.devnull will be used. DEVNULL表示将使用特殊文件os.devnull With the default settings of None , 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM