简体   繁体   English

将`sys.stdout`重定向到文件或缓冲区

[英]Redirecting `sys.stdout` to a file or a buffer

I am working in Python 3.4, and I have behavior that I don't understand: if I redirect stdout to a file, I am able to capture text from child processes. 我在Python 3.4中工作,我有一些我不理解的行为:如果我将stdout重定向到一个文件,我能够从子进程中捕获文本。 However, when I redirect to a Python file object, I stop capturing that output. 但是,当我重定向到Python文件对象时,我停止捕获该输出。 I would love an explanation of the (following) behavior. 我很想解释(跟随)行为。

I have: 我有:

from multiprocessing import Process

def worker():
    print('forked output')

def output():
    print('redirected')
    p = Process(target=worker)
    p.daemon = True
    p.start()
    p.join()  # wait for subprocess to terminate
    print('end')

The redirect_stdout context manager in Python 3.4 makes grabbing stdout easy (in this instance). Python 3.4中的redirect_stdout上下文管理器使得stdout变得容易(在这个例子中)。

from contextlib import redirect_stdout
from sys import stdout
from tempfile import TemporaryFile


with TemporaryFile(mode='w+', encoding=stdout.encoding) as buf:
    with redirect_stdout(buf):
        output()  # the function defined above
    buf.seek(0)
    s = buf.read()
    print('output from TemporaryFile:')
    print(s)

I can then simply call the script to get the following output: 然后我可以简单地调用脚本来获得以下输出:

$ python stackoverflow.py 
output from TemporaryFile:
redirected
forked output
end

This is exactly what I want, and works fine. 这正是我想要的,并且工作正常。

My confusion stems from the fact that if I if I switch TemporaryFile with TextIOWrapper , the behavior of my script changes. 我的困惑源于这样一个事实:如果我用TextIOWrapper切换TemporaryFile ,我脚本的行为就会改变。

from io import BytesIO, TextIOWrapper


with TextIOWrapper(BytesIO(), stdout.encoding) as buf:
    with redirect_stdout(buf):
        output()  # the function defined at the start
    buf.seek(0)
    s = buf.read()
    print('output from TextIO:')
    print(s)

Now when I call the program, I lose the output from the forked process. 现在,当我调用程序时,我丢失了分叉进程的输出。

$ python stackoverflow.py 
output from TextIO:
redirected
end

What is going on? 到底是怎么回事?

I suspect the problem has to do with the fact that the TextIOWrapper object doesn't have a file descriptor, and that os.fork() (used by multiprocessing ) may thus be replacing the TextIOWrapper with another, but I admit some confusion there (especially given that stdout appears to be a TextIOWrapper with fileno() implemented). 我怀疑问题与TextIOWrapper对象没有TextIOWrapper这一事实有关,并且os.fork() (由multiprocessing )可能因此将TextIOWrapper替换为另一个,但我承认有些困惑(特别是鉴于stdout似乎是一个带有 fileno()实现的TextIOWrapper )。

>>> from sys import stdout
>>> stdout.fileno()
1
>>> stdout
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>

Thanks for any information. 感谢您提供任何信息。

Since you're using multiprocessing, you should use the standard message passing primitives provided by that library. 由于您正在使用多处理,因此应使用该库提供的标准消息传递原语 Do not call print() from the subprocess; 不要从子进程调用print() ; that's poor design. 这是糟糕的设计。

If you're actually trying to make this work with someone else's (non-Python) code, use subprocess.check_output() or another of the subprocess functions instead. 如果您实际上正在尝试使用其他人的(非Python)代码,请使用subprocess.check_output()或其他子进程函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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