2014-04-22 20 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) 

內容一個命名管道不接觸磁盤。