[英]Python: subprocess32 process.stdout.readline() waiting time
如果我使用例如“ls -Rlah /”運行以下函數“run”,我會立即通過print語句獲得輸出
import subprocess32 as subprocess
def run(command):
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
try:
while process.poll() == None:
print process.stdout.readline()
finally:
# Handle the scenario if the parent
# process has terminated before this subprocess
if process.poll():
process.kill()
但是,如果我使用下面的python示例程序,它似乎停留在process.poll()或process.stdout.readline()上,直到程序完成。 我認為它是stdout.readline(),因為如果我將輸出的字符串數量從10增加到10000(在示例程序中)或者在每次打印后添加到sys.stdout.flush()中,則在運行中打印函數確實被執行了。
如何使子進程的輸出更加實時?
注意:我剛剛發現python示例程序在輸出時不執行sys.stdout.flush(),是否有一種方法讓子進程的調用者以某種方式強制執行此操作?
每5秒輸出10個字符串的示例程序。
#!/bin/env python
import time
if __name__ == "__main__":
i = 0
start = time.time()
while True:
if time.time() - start >= 5:
for _ in range(10):
print "hello world" + str(i)
start = time.time()
i += 1
if i >= 3:
break
在大多數系統上,命令行程序行緩沖區或塊緩沖區,具體取決於stdout
是終端還是管道。 在unixy系統上,即使子節點並非真正從終端運行,父進程也可以創建一個偽終端來獲得類似終端的行為。 您可以使用pty
模塊創建偽終端或使用pexpect
模塊,以便輕松訪問交互式程序。
正如評論中所提到的,使用poll
來讀取行會導致數據丟失。 一個例子是當進程終止時在stdout管道中留下的數據。 讀取pty
與管道有點不同,你會發現當孩子關閉時需要捕獲一個IOError,以使其全部正常工作,如下例所示。
try:
import subprocess32 as subprocess
except ImportError:
import subprocess
import pty
import sys
import os
import time
import errno
print("running %s" % sys.argv[1])
m,s = (os.fdopen(pipe) for pipe in pty.openpty())
process = subprocess.Popen([sys.argv[1]],
stdin=s,
stdout=s,
stderr=subprocess.STDOUT)
s.close()
try:
graceful = False
while True:
line = m.readline()
print line.rstrip()
except IOError, e:
if e.errno != errno.EIO:
raise
graceful = True
finally:
# Handle the scenario if the parent
# process has terminated before this subprocess
m.close()
if not graceful:
process.kill()
process.wait()
您應該在腳本中刷新標准輸出:
print "hello world" + str(i)
sys.stdout.flush()
當標准輸出是終端時,stdout是行緩沖的。 但是當它不是時,stdout是塊緩沖的,你需要顯式刷新它。
如果無法更改腳本的源代碼,可以使用Python的-u
選項(在子進程中):
-u Force stdin, stdout and stderr to be totally unbuffered.
你的命令應該是: ['python', '-u', 'script.py']
通常,這種緩沖發生在用戶空間中。 沒有通用的方法來強制應用程序刷新其緩沖區:某些應用程序支持命令行選項(如Python),其他應用程序支持信號,其他應用程序不支持任何內容。
一種解決方案可能是模擬偽終端,給程序提供“提示”,它們應該在行緩沖模式下運行。 盡管如此,這並不是一個適用於所有情況的解決方案。
對於除python以外的東西,你可以嘗試使用unbuffer :
unbuffer禁用從非交互式程序重定向程序輸出時發生的輸出緩沖。 例如,假設您通過運行od然后更多來查看fifo的輸出。 od -c / tmp / fifo | 更多在產生整頁輸出之前,您不會看到任何內容。 您可以按如下方式禁用此自動緩沖:
unbuffer od -c /tmp/fifo | more
通常,unbuffer不會從stdin讀取。 這在某些情況下簡化了unbuffer的使用。 要在管道中使用unbuffer,請使用-p標志。 示例:process1 | unbuffer -p process2 | process3
所以在你的情況下:
run(["unbuffer",cmd])
文檔中列出了一些警告,但這是另一種選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.