gpt4 book ai didi

python - 子进程 stderr 与 sys.stderr

转载 作者:太空宇宙 更新时间:2023-11-03 14:41:39 27 4
gpt4 key购买 nike

我不确定这个问题是 Python 还是 shell 问题。

我有一个 Python 程序,它在命令上使用子进程调用,该命令可以在 stderr 上发出错误消息。我自己的程序也使用 sys.stderr 来记录错误。这是一个简单的示例,其中的命令 (ls *.foobar) 失败了:

import sys,subprocess

sys.stderr.write("--Hello\n")
try:
subprocess.check_call("ls *.foobar",shell=True)
except subprocess.CalledProcessError as e:
sys.stderr.write("Command failed\n")
sys.stderr.write("--Bye\n")

当我运行这段代码时,控制台上的输出(来自 stderr)如下:

--Hello
ls: cannot access '*.foobar': No such file or directory
Command failed
--Bye

如果我将 stderr 重定向到一个文件(例如使用 python myscript.py 2> log),该文件包含以下内容:

ls: cannot access '*.foobar': No such file or directory
--Hello
Command failed
--Bye

有没有办法保持文件中消息的顺序(除了在子进程调用中对文件使用 stderr 的显式重定向)?

这个问题类似于一些标准的 stdout/stderr 问题,但在这里,一切都应该在 stderr 上。

最佳答案

您需要将数据写入器刷新stderr 描述符:

sys.stderr.write("--Hello\n")
sys.stderr.flush()

stdio 在连接到终端时是行缓冲的,而在连接到管道时使用固定缓冲区。您正在编写一个 \n 换行符,它在连接到终端时会触发刷新,但是,如果没有每行刷新,您不会向 stderr 写入足够的内容来触发Python 退出时最终刷新之前的缓冲区刷新。

如果你使用 print(..., file=sys.stderr) 你可以告诉 print() 发出 flush() 通过添加 flush=True 调用:

print("--Hello", file=sys.stderr, flush=True)

处理此问题的另一种方法是“捕获并释放”子进程的 stderr 输出:

sys.stderr.write("--Hello\n")
try:
subprocess.check_call("ls *.foobar", shell=True, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
sys.stderr.write(e.stderr)
sys.stderr.write("Command failed\n")
sys.stderr.write("--Bye\n")

stderr=subprocess.PIPE 添加项告诉 subprocess 捕获命令的 stderr 输出,您可以找到该输出作为 e.stderr CalledProcessError 异常的属性。

关于python - 子进程 stderr 与 sys.stderr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52780404/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com