的讀標準輸出我有一個腳本(worker.py),該打印的形式無緩衝輸出...的Python:非阻塞從螺紋子
1
2
3
.
.
.
n
其中n是迭代在該循環的一些恆定數腳本將使。在另一個腳本(service_controller.py)中,我啓動了多個線程,每個線程使用subprocess.Popen(stdout = subprocess.PIPE,...)啓動一個子進程;現在,在我的主線程(service_controller.py)中,我想讀取每個線程的worker.py子進程的輸出,並使用它計算剩餘時間直到完成的估計值。
我有所有的邏輯工作,從worker.py讀取stdout並確定最後打印的數字。問題是,我無法弄清楚如何以非阻塞的方式做到這一點。如果我讀取一個常量bufsize,那麼每次讀取都將最終等待來自每個工作人員的相同數據。我嘗試了很多方法,包括使用fcntl,select + os.read等。這裏我最好的選擇是什麼?如果需要,我可以發佈我的源代碼,但我認爲解釋很好地描述了問題。
感謝您的任何幫助。
編輯
添加示例代碼
我有一個啓動子工人。
class WorkerThread(threading.Thread):
def __init__(self):
self.completed = 0
self.process = None
self.lock = threading.RLock()
threading.Thread.__init__(self)
def run(self):
cmd = ["/path/to/script", "arg1", "arg2"]
self.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=1, shell=False)
#flags = fcntl.fcntl(self.process.stdout, fcntl.F_GETFL)
#fcntl.fcntl(self.process.stdout.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)
def get_completed(self):
self.lock.acquire();
fd = select.select([self.process.stdout.fileno()], [], [], 5)[0]
if fd:
self.data += os.read(fd, 1)
try:
self.completed = int(self.data.split("\n")[-2])
except IndexError:
pass
self.lock.release()
return self.completed
然後我有一個ThreadManager。
class ThreadManager():
def __init__(self):
self.pool = []
self.running = []
self.lock = threading.Lock()
def clean_pool(self, pool):
for worker in [x for x in pool is not x.isAlive()]:
worker.join()
pool.remove(worker)
del worker
return pool
def run(self, concurrent=5):
while len(self.running) + len(self.pool) > 0:
self.clean_pool(self.running)
n = min(max(concurrent - len(self.running), 0), len(self.pool))
if n > 0:
for worker in self.pool[0:n]:
worker.start()
self.running.extend(self.pool[0:n])
del self.pool[0:n]
time.sleep(.01)
for worker in self.running + self.pool:
worker.join()
和一些代碼來運行它。
threadManager = ThreadManager()
for i in xrange(0, 5):
threadManager.pool.append(WorkerThread())
threadManager.run()
我已經刪除了其他代碼的日誌,希望能夠查明問題。
你在Linux或其他Unix?如果是這樣,請選擇+ os.read 1字節應該可以正常工作 - 您能告訴我們您沿該行的代碼以及它給您帶來的錯誤或不當行爲嗎? –
這實際上是用於開發的Windoze,它將在Fedora或OS X上進行生產。 – sberry