为什么子进程的标准输出(重定向到无缓冲文件)被缓冲?

发布于 2024-11-05 08:33:44 字数 955 浏览 1 评论 0原文

来自 http://docs.python.org/library/functions.html#open

可选的 bufsize 参数 指定文件所需的缓冲区 size:0表示无缓冲,1表示行 缓冲,任何其他正值 意味着使用(大约)的缓冲区 那个尺寸。负的 bufsize 意味着 使用系统默认值,即 通常为 tty 设备进行行缓冲 并为其他文件完全缓冲。如果 省略,使用系统默认。

我在下面传递 0 作为 bufsize,但没有使用lush(),当我运行 main_process 时,没有输出写入文件。
原因是什么?

# --------------------------------- sub_process.py
import sys
import time

if __name__ == '__main__':
    print 'printed from redirect.py'
    # why is the following flush() needed? 'std-output' is (?) unbuffered...
    sys.stdout.flush() 
    time.sleep(6)


# --------------------------------- main_process.py
import subprocess
import time

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', 'sub_process.py'],
        stdout=open('std-output', 'w', 0))
    time.sleep(3)
    p.terminate()

From http://docs.python.org/library/functions.html#open

The optional bufsize argument
specifies the file’s desired buffer
size: 0 means unbuffered, 1 means line
buffered, any other positive value
means use a buffer of (approximately)
that size. A negative bufsize means to
use the system default, which is
usually line buffered for tty devices
and fully buffered for other files. If
omitted, the system default is used.

I'm passing 0 as bufsize below yet without using flush() there's no output written to the file when I run main_process.
What's the reason?

# --------------------------------- sub_process.py
import sys
import time

if __name__ == '__main__':
    print 'printed from redirect.py'
    # why is the following flush() needed? 'std-output' is (?) unbuffered...
    sys.stdout.flush() 
    time.sleep(6)


# --------------------------------- main_process.py
import subprocess
import time

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', 'sub_process.py'],
        stdout=open('std-output', 'w', 0))
    time.sleep(3)
    p.terminate()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感性 2024-11-12 08:33:44

使用带有 -u 标志的 python,例如:

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', '-u', 'sub_process.py'],
        stdout=open('std-output', 'w'))
    time.sleep(3)
    p.terminate()

Use python with the -u flag, e.g.:

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', '-u', 'sub_process.py'],
        stdout=open('std-output', 'w'))
    time.sleep(3)
    p.terminate()
沉默的熊 2024-11-12 08:33:44

扩展 Magnus Skog 解决方案(顺便说一下 +1 :) ):

基本上,当子进程分叉一个新进程时,它会使用 os.dup2 将 stdout 参数复制到新的子进程 stdout (fileno = 1) (看看subprocess.Popen._execute_child),这将保持无缓冲状态(就像dup2 做的),到目前为止一切都很好,但是当默认情况下启动 python 时(在子进程中),如果 python 没有看到 -u 标志,它将把 stdout 的缓冲区设置为行缓冲区(看看 < a href="http://hg.python.org/cpython/file/bcf04ced5ef1/Modules/main.c#l454">main python function.)这将覆盖您之前设置的缓冲标志。

希望这能更多地解释您所看到的行为。

Extending Magnus Skog solution (+1 by the way :) ):

Well basically what happen is that when subprocess will fork a new process it will duplicate the stdout argument to the new subprocess stdout (fileno = 1) using os.dup2 (look at subprocess.Popen._execute_child) and this will keep the unbuffered state (as what dup2 do), everything until now is good, but when python will be launched (in the subprocess) by default if python don't see the -u flag it will set the buffer of stdout to line buffer (take a look at the main python function.) which will override the buffering flag that you set before.

Hope this explain more the behavior that you was seeing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文