python-3.x 通过subprocess.run()和TextIOWrapper写入文件,write()混淆

6l7fqoea  于 2022-12-01  发布在  Python
关注(0)|答案(1)|浏览(138)

运行以下代码片段时

import subprocess

with open('test', 'w') as f:
    f.write('foo\n')
    subprocess.run(['echo', 'bar'], stdout=f)

我实际上希望创建一个文件test,其中第一行等于foo,第二行等于bar

bar
foo

我想知道上面代码片段的正确Python版本应该是什么样子的,首先写foo,然后写bar。当然,我可以将这两个操作拆分成两个不同的with语句,如下所示:

import subprocess

with open('test', 'w') as f:
    f.write('foo\n')
with open('test', 'a') as f:
    subprocess.run(['echo', 'bar'], stdout=f)

不过,这是相当糟糕的意义上,文件必须打开/关闭两次,现在。有什么更好的解决方案吗?

mo49yndu

mo49yndu1#

这很可能是由于文件上的隐式缓冲造成的。
如果您在写入foo * 之后 * 但在启动子进程之前添加显式flush(),则它应该按预期工作:

import subprocess

with open('test', 'w') as f:
    f.write('foo\n')
    f.flush()
    subprocess.run(['echo', 'bar'], stdout=f)

或者,您可以在打开文件 * 时 * 禁用文件缓冲。通常不建议这样做,除非您知道自己在做什么,因为许多I/O模式在没有缓冲的情况下会降级:

import subprocess

with open('test', 'w', buffering=1) as f:
    f.write('foo\n')
    subprocess.run(['echo', 'bar'], stdout=f)

从技术上讲,上面的方法不是 * 禁用 * 缓冲,而是启用 * 面向行 * 缓冲。也就是说,每当你写一个换行符时,文件会自动刷新(就像你写“foo”之后所做的那样)。要完全禁用缓冲,你需要以二进制模式写:

import subprocess

with open('test', 'wb', buffering=0) as f:
    f.write(b'foo\n')
    subprocess.run(['echo', 'bar'], stdout=f)

相关问题