[英]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()
注意:除非你調用.communicate()
; 只要任何stdout / stderr OS管道緩沖區填滿, diff
進程就會掛起。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.