[英]Python 2 to 3 conversion: iterating over lines in subprocess stdout
我有以下Python 2示例代碼,我想與Python 3兼容:
call = 'for i in {1..5}; do sleep 1; echo "Hello $i"; done'
p = subprocess.Popen(call, stdout=subprocess.PIPE, shell=True)
for line in iter(p.stdout.readline, ''):
print(line, end='')
這在Python 2中運行良好,但在Python 3中, p.stdout
不允許我指定編碼並且讀取它將返回字節字符串而不是Unicode,因此與''
的比較將始終返回false並且iter
將不會停止。 這個問題似乎暗示在Python 3.6中有一種定義這種編碼的方法。
現在,我已經將iter
調用更改為當它找到一個空字節字符串iter(p.stdout.readline, b'')
時停止,這似乎在2和3中工作。我的問題是:這兩個都安全嗎?和3? 有沒有更好的方法來確保兼容性?
注意:我沒有for line in p.stdout:
使用for line in p.stdout:
因為我需要在生成時打印每一行,根據這個答案 p.stdout
有一個太大的緩沖區。
您可以添加unversal_newlines=True
。
p = subprocess.Popen(call, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
for line in iter(p.stdout.readline, ''):
print(line, end='')
而不是bytes
,將返回str
因此''
將在兩種情況下都有效。
以下是文檔對該選項的說法:
如果universal_newlines為False,則文件對象stdin,stdout和stderr將作為二進制流打開,並且不會進行行結束轉換。
如果universal_newlines為True,則這些文件對象將使用locale.getpreferredencoding(False)返回的編碼以通用換行模式打開為文本流。 對於stdin,輸入中的行結束字符'\\ n'將轉換為默認行分隔符os.linesep。 對於stdout和stderr,輸出中的所有行結尾都將轉換為'\\ n'。 有關更多信息,請參閱io.TextIOWrapper類的文檔,當其構造函數的換行參數為None時。
它沒有明確地提到bytes
與str
區別,但是通過聲明False
返回二進制流並且True
返回文本流來暗示它。
你可以使用p.communicate()
然后解碼它,如果它是一個bytes
對象:
from __future__ import print_function
import subprocess
def b(t):
if isinstance(t, bytes):
return t.decode("utf8")
return t
call = 'for i in {1..5}; do sleep 1; echo "Hello $i"; done'
p = subprocess.Popen(call, stdout=subprocess.PIPE, shell=True)
stdout, stderr = p.communicate()
for line in iter(b(stdout).splitlines(), ''):
print(line, end='')
這適用於Python 2和Python 3
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.