簡體   English   中英

通過Python中的多個命名管道將字符串作為子進程輸入傳遞

[英]Pass strings as subprocess' input via multiple named pipes in Python

我花了相當多的時間試圖讓Linux差異和補丁工具在python中使用字符串。 為了實現這一點,我嘗試使用命名管道,因為它們似乎是最強大的方法。 問題是這不適用於大文件。

例:

a, b = str1, str2 # ~1MB each string

fname1, fname2 = mkfifos(2)
proc = subprocess.Popen(['diff', fname1, fname2], \
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

print('Writing first file.')
with open(fname1, 'w') as f1:
    f1.write(a)
print('Writing second file.')
with open(fname2, 'w') as f2:
    f2.write(b)

這在第一次寫作時就會掛起。 如果弄清楚如果我使用a[:6500]它會在第二次寫入時掛起。 所以我認為它與緩沖區有關。 我嘗試在每次寫入,關閉之后手動刷新,使用低級別的os.open(f, 'r', 0)和0緩沖區,但仍然是同樣的問題。

我想到了在塊中編寫循環,但在像Python這樣的高級語言中感覺不對。 我有什么想法我做錯了嗎?

命名管道仍然是管道。 它在Linux上有一個有限的緩沖區。 除非有人同時從管道的另一端讀取,否則您無法寫入無限輸出。

如果f1.write(a)阻塞則意味着diff不會立即讀取所有輸入文件(這似乎是合乎邏輯的: diff程序的目的是逐行比較文件 - 從第一個文件讀取不會遠遠超過第二個文件的讀數)。

要同時將不同的數據寫入不同的位置,可以使用threads / async.io:

#!/usr/bin/env python3
from subprocess import Popen, PIPE
from threading import Thread

def write_input_async(path, text):
    def writelines():
        with open(path, 'w') as file:
            for line in text.splitlines(keepends=True):
                file.write(line)
    Thread(target=writelines, daemon=True).start()

with named_pipes(2) as paths, \
    Popen(['diff'] + paths, stdout=PIPE,stderr=PIPE, universal_newlines=True) as p:
    for path, text in zip(paths, [a, b]):
        write_input_async(path, text)
    output, errors = p.communicate()

其中named_pipes(n)上下文管理器在這里定義

注意:除非你調用.communicate() ; 只要任何stdout / stderr OS管道緩沖區填滿, diff進程就會掛起。


您可以考慮difflib.context_diff(a, b)是否適用於您的情況

暫無
暫無

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

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