2014-04-22 21 views
1

我想在2个命名临时文件上运行diff,我没有使用difflib,因为它的输出与linux diff不同。 当我运行这段代码时,它不输出任何东西。我尝试了一些常规文件的差异,并且工作得很好。需要使用子进程模块在2 NamedTemporaryFiles上运行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]) 
+0

你试过了吗:['print(''。join(difflib.ndiff(stage_notes,prod_notes)))'](https://docs.python.org/2/library/difflib.html#difflib.ndiff )而不是? – jfs

回答

3

您需要强制文件,通过调用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]) 
+0

非常感谢,从来没有想到这一点。 –

2

我建议绕过临时文件处理,因为用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() 

然后运行您的通话子

2

完全无关的.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从标准输入读取IF输入文件名是-

如果您使用命名管道,那么你就不需要写在所有的磁盘上的内容:

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) 

内容一个命名管道不接触磁盘。