我正试图在两个命名的临时文件上运行diff,我没有使用difflib,因为它的输出与linux diff不同。当我运行此代码时,它不会输出任何内容。我在普通文件上尝试了diff,效果很好。
#using python 2.6
temp_stage = tempfile.NamedTemporaryFile(delete = False)
temp_prod = tempfile.NamedTemporaryFile(delete = False)
temp_stage.write(stage_notes)
temp_prod.write(prod_notes)
#this does not work, shows no output, tried both call and popen
subprocess.Popen(["diff", temp_stage.name, temp_prod.name])
#subprocess.call(["diff", temp_stage.name, temp_prod.name])
您需要通过调用flush()
来强制将文件写入磁盘;否则,写入文件的数据可能只存在于缓冲区中。
事实上,如果您这样做,您甚至可以使用delete = True
,假设没有其他理由可以保留这些文件。这保留了使用tempfile的好处。
#!/usr/bin/python2
temp_stage = tempfile.NamedTemporaryFile(delete = True)
temp_prod = tempfile.NamedTemporaryFile(delete = True)
temp_stage.write(stage_notes)
temp_prod.write(prod_notes)
temp_stage.flush()
temp_prod.flush()
subprocess.Popen(["diff", temp_stage.name, temp_prod.name])
与.flush()
问题无关,您可以通过stdin传递一个文件,而不是将数据写入磁盘:
from tempfile import NamedTemporaryFile
from subprocess import Popen, PIPE
with NamedTemporaryFile() as file:
file.write(prod_notes)
file.flush()
p = Popen(['diff', '-', file.name], stdin=PIPE)
p.communicate(stage_notes) # diff reads the first file from stdin
if p.returncode == 0:
print('the same')
elif p.returncode == 1:
print('different')
else:
print('error %s' % p.returncode)
如果输入文件名为-
,则diff
从stdin读取。
如果您使用命名管道,则根本不需要将数据写入磁盘:
from subprocess import Popen, PIPE
from threading import Thread
with named_pipe() as path:
p = Popen(['diff', '-', path], stdin=PIPE)
# use thread, to support content larger than the pipe buffer
Thread(target=p.communicate, args=[stage_notes]).start()
with open(path, 'wb') as pipe:
pipe.write(prod_notes)
if p.wait() == 0:
print('the same')
elif p.returncode == 1:
print('different')
else:
print('error %s' % p.returncode)
其中named_pipe()
上下文管理器定义为:
import os
import tempfile
from contextlib import contextmanager
from shutil import rmtree
@contextmanager
def named_pipe(name='named_pipe'):
dirname = tempfile.mkdtemp()
try:
path = os.path.join(dirname, name)
os.mkfifo(path)
yield path
finally:
rmtree(dirname)
命名管道的内容不会接触到磁盘。
我建议绕过临时文件处理,因为使用NTF,无论如何都必须处理清理。创建一个新文件并写入数据,然后关闭它。刷新缓冲区,然后调用子流程命令。看看这是否能让它运转起来。
f=open('file1.blah','w')
f2=open('file2.blah','w')
f.write(stage_notes)
f.flush()
f.close()
f2.write(prod_notes)
f2.flush()
f2.close()
然后运行您的子流程调用