通过subprocess.run()和TextIOWrapper.write()写入文件混淆了 &g



运行以下代码片段

import subprocess
with open('test', 'w') as f:
f.write('foon')
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('foon')
with open('test', 'a') as f:
subprocess.run(['echo', 'bar'], stdout=f)

虽然,这是相当糟糕的,因为文件必须打开/关闭两次,现在。有没有更好的解决办法?

由于文件的隐式缓冲,这很可能发生。

如果在写入foo之后但在启动子进程之前添加显式的flush(),它应该像预期的那样工作:

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

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

import subprocess
with open('test', 'w', buffering=1) as f:
f.write('foon')
subprocess.run(['echo', 'bar'], stdout=f)
从技术上讲,上面的并不是禁用缓冲,而是启用面向行的缓冲。也就是说,每当您写入换行符时,文件将自动刷新(就像您在写入&;foo&;之后所做的那样)。要完全禁用缓冲,您需要以二进制模式写入:
import subprocess
with open('test', 'wb', buffering=0) as f:
f.write(b'foon')
subprocess.run(['echo', 'bar'], stdout=f)

最新更新