【发布时间】:2021-12-17 05:29:30
【问题描述】:
我正在尝试将标准输出写入文件以获取在子进程中运行的内容。我的问题是我的输出总是被截断为 4096 字节(一页大小),我认为这是由于 x86 系统上的 PIPE 大小造成的?
我这样设置我的子流程
with open("newfile.txt", "w") as f:
proc = subprocess.Popen([find_executable(bin_name), *extra_args],
stdout=f, stderr=subprocess.DEVNULL)
让它在做其他事情的同时运行,然后
def shutdown(process):
if process.poll() is None:
try:
process.terminate()
process.wait(timeout.PROCESS_QUIT)
except subprocess.TimeoutExpired:
print(f"Process {process.args} not terminating after {timeout.PROCESS_QUIT} sec.",
file=sys.stderr)
process.kill()
newfile.txt 中的输出总是精确地打印 4096 字节然后截断(通常是中间行)
我尝试过定期添加 context.file_to_close.flush() 但这似乎并没有任何影响。如何将整个 stdout 打印到文件中?
strace 给了我 7000 多行的输出,我不太确定如何阅读,但这似乎是与 newfile.txt 相关的所有内容?
openat(AT_FDCWD, "newfile.txt", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 6
fstat(6, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
ioctl(6, TCGETS, 0x7ffc05c3fac0) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(6, 0, SEEK_CUR) = 0
ioctl(6, TCGETS, 0x7ffc05c3f9c0) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(6, 0, SEEK_CUR) = 0
stat("/basepath/project/build-behave/the_app.app", {st_mode=S_IFREG|0755, st_size=5355744, ...}) = 0
openat(AT_FDCWD, "/dev/null", O_RDWR|O_CLOEXEC) = 7
pipe2([8, 9], O_CLOEXEC) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb12fc44a10) = 1349
close(9) = 0
close(7) = 0
read(8, "", 50000) = 0
close(8) = 0
close(6) = 0
(根据 mata 和 Charles Duffy 的建议编辑代码)
【问题讨论】:
-
应该与管道尺寸无关。文件句柄直接传递给启动的进程,并写入那里。应该不需要在父进程中刷新它。您还对父级中的文件做什么?
-
没有别的了。我打开文件,在 Popen 时将其提供给子进程,将文件句柄存储在行为测试上下文中,然后在终止子进程后关闭它
-
我假设存在管道大小问题,因为我最初将 stdout 写入 subprocess.PIPE 并且由于此问题 bugs.python.org/issue41586 而上限为 4096。写入文件是我试图绕过这个限制
-
该进程是否向 stderr 写入了很多内容,您正在阅读吗?如果您在进程运行时没有使用它,您的问题可能是进程在写入该管道时阻塞。如果您不阅读它,请将其发送到 subprocess.DEVNULL。而且似乎没有理由在上下文中保持文件打开,您应该在启动子进程后立即关闭它(它不会在那里关闭)。
-
啊,好的,很高兴知道,谢谢!我将我的标准错误重定向到 subprocess.DEVNULL 并在弹出后立即关闭了文件。 newfile.txt 似乎仍然在同一点被截断
标签: python subprocess pipe python-3.8