簡體   English   中英

python-比較新寫入的文件與filecmp.cmp()總是返回False?

[英]python - comparing a newly written file with filecmp.cmp() always returns False?

我肯定在這里犯了一個愚蠢的錯誤,因為這應該起作用。 我在想文件保持打開狀態,或者讓我發瘋。

這是針對某些回歸測試用例的,我在這里比較腳本生成的輸出與模擬文件與已知良好的輸出文件(關鍵文件)的比較。

這是一個簡單的示例:

def run_and_compare(self, key_file, out_file, option):
    print filecmp.cmp(out_file, key_file) # always True (as long as I've run this before, so the out_file exists already)
    cmd = './analyze_files.py -f option'
    with open(out_file, 'wb') as out:
        subprocess.Popen(cmd.split(), stdout=out, stderr=subprocess.PIPE)
    print filecmp.cmp(out_file, key_file) # always False 
    time.sleep(5)
    print filecmp.cmp(out_file, key_file) # always True 

我真的不想在測試中保持睡眠! 如何確定不使用睡眠即可比較out文件? 我嘗試使用out.close(),但是它不起作用,並且只要我使用“ with”就不需要。 我在這里使用python 2.6.4。

將輸出文件對象作為上下文管理器打開都沒關系。 如果您明確地手動關閉文件對象,甚至都沒有關系。

這是因為當您將Python文件對象傳遞給subprocess.Popen() ,從該文件對象獲取的只是文件handle ,這是操作系統用來與打開的文件進行通訊的整數。 然后,子進程使用os.dup2()將文件句柄克隆到子進程的STDOUT文件句柄上。 這就是導致該子進程的輸出進入磁盤上指定文件的原因。

由於文件句柄是偽造的,因此關閉原始Python文件對象(間接地,也就是原始OS文件句柄) 實際上不會關閉文件,因為第二個文件句柄仍保持打開狀態。

等待幾秒鍾后看到文件數據出現的原因是,最終創建的子進程將完成, 然后才關閉其他重復的文件句柄。

不用等待幾秒鍾,而是使用Popen.communicate()方法等待子過程完成:

p = subprocess.Popen(cmd.split(), stdout=open(out_file, 'wb'),
                     stderr=subprocess.PIPE)
stdout, stderr = p.communicate()  # stdout will always be None

我內聯了open()調用,因為一旦subprocess.Popen()從該文件對象檢索到文件句柄,該文件對象就沒有其他用途。 您也可以使用os.open()代替open() (相同的參數),並安全地創建僅文件句柄就足夠的Python文件對象。

不要使用p.wait() ; 因為您在子進程的STDERR流中使用管道 ,所以如果您從STDERR中讀取數據 ,但是子進程向其中寫入了大量數據,則可以使進程死鎖。 您最終將永遠等待。

我建議您在子流程中添加一個wait ,以等待其完成

with open(out_file, 'wb') as out:
    p=subprocess.Popen(cmd.split(), stdout=out, stderr=subprocess.PIPE)
    p.wait()

如果不等待,子進程將啟動,將文件作為輸出out並立即返回(在后台啟動)。 比較兩個文件時,一個文件可能為空,因此為False。

過一會兒,子進程結束, out不再使用,可能是垃圾回收,句柄關閉:您的文件有效。 (我並不是說這就是這里發生的事情,但是缺少p.wait()肯定是這里的問題)

除此之外,我一直想知道為什么人們在這么簡單的情況下就運行涉及python命令的子流程,以便直接導入它們並直接調用其功能,從而受益於異常鏈,這是唯一的流程,從而避免了所有這些進程間通信問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM