[英]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.