[英]subprocess.Popen stdin read file
我正在嘗試在讀取文件的一部分后調用文件的進程。 例如:
with open('in.txt', 'r') as a, open('out.txt', 'w') as b:
header = a.readline()
subprocess.call(['sort'], stdin=a, stdout=b)
如果我在執行 subprocess.call 之前沒有從 a 中讀取任何內容,這將正常工作,但是如果我從中讀取任何內容,則子流程將看不到任何內容。 這是使用 python 2.7.3。 我在文檔中找不到任何解釋這種行為的內容,並且(非常)簡短地瀏覽了子流程源並沒有發現原因。
如果您無緩沖地打開文件,則它可以工作:
import subprocess
with open('in.txt', 'rb', 0) as a, open('out.txt', 'w') as b:
header = a.readline()
rc = subprocess.call(['sort'], stdin=a, stdout=b)
subprocess
模塊在文件描述符級別(操作系統的低級別無緩沖 I/O)工作。 如果操作系統支持,它可以與os.pipe()
、 socket.socket()
、 pty.openpty()
以及任何具有有效.fileno()
方法的東西一起使用。
不建議在同一個文件上混合緩沖和非緩沖 I/O。
在 Python 2 上, file.flush()
導致輸出出現,例如:
import subprocess
# 2nd
with open(__file__) as file:
header = file.readline()
file.seek(file.tell()) # synchronize (for io.open and Python 3)
file.flush() # synchronize (for C stdio-based file on Python 2)
rc = subprocess.call(['cat'], stdin=file)
這個問題可以不被復制subprocess
模塊os.read()
#!/usr/bin/env python
# 2nd
import os
with open(__file__) as file: #XXX fully buffered text file EATS INPUT
file.readline() # ignore header line
os.write(1, os.read(file.fileno(), 1<<20))
如果緩沖區大小很小,則打印文件的其余部分:
#!/usr/bin/env python
# 2nd
import os
bufsize = 2 #XXX MAY EAT INPUT
with open(__file__, 'rb', bufsize) as file:
file.readline() # ignore header line
os.write(2, os.read(file.fileno(), 1<<20))
如果第一行的大小不能被bufsize
整除,它會消耗更多的輸入。
默認的bufsize
和bufsize=1
(行緩沖)在我的機器上表現相似:文件的開頭消失了——大約 4KB。
file.tell()
報告所有緩沖區大小的第 2 行開頭的位置。 由於預讀緩沖區錯誤( io.open()
給出了預期的第 2 行位置),使用next(file)
而不是file.readline()
在我的 Python 2 機器上導致file.tell()
大約 5K。
在子file.seek(file.tell())
調用之前嘗試file.seek(file.tell())
對具有默認基於 stdio 的文件對象的 Python 2 沒有幫助。 它與 Python 2 上的io
、 _pyio
模塊中的open()
函數以及 Python 3 上的默認open
(也是基於io
的)一起使用。
使用和不使用file.flush()
在 Python 2 和 Python 3 上嘗試io
、 _pyio
模塊會產生各種結果。 它確認在同一個文件描述符上混合緩沖和非緩沖 I/O 不是一個好主意。
這是因為子進程模塊從文件對象中提取文件句柄。
http://hg.python.org/releasing/2.7.6/file/ba31940588b6/Lib/subprocess.py
在第 1126 行,來自 701。
文件對象使用緩沖區,並且在子進程提取文件句柄時已經從文件句柄中讀取了很多內容。
正如@jfs 提到的,在使用 popen 時,它會將文件描述符傳遞給進程,同時 python 讀取塊(例如 4096 字節),結果是 fd 級別的位置與您期望的不同。
我通過對齊文件描述符位置在 python 2.7 中解決了它。
_file = open(some_path)
_file.read(codecs.BOM_UTF8)
os.lseek(_file.fileno(), _file.tell(), os.SEEK_SET)
truncate_null_cmd = ['tr','-d', '\\000']
subprocess.Popen(truncate_null_cmd, stdin=_file, stdout=subprocess.PIPE)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.