5

pty次のようなプロセスの stdout をブロックしない読み取りに使用しています。

import os
import pty
import subprocess

master, slave = pty.openpty()

p = subprocess.Popen(cmd, stdout = slave)

stdout = os.fdopen(master)
while True:
    if p.poll() != None:
        break

    print stdout.readline() 

stdout.close()

while-loop時々ブロックすることを除いて、すべて正常に動作します。これは、行print stdout.readline()が から何かが読み取られるのを待っているためですstdout。しかし、プログラムが既に終了している場合、そこにある私の小さなスクリプトは永遠にハングアップします。

私の質問は次のとおりです。stdoutオブジェクトを覗き込んで、読み取り可能なデータがあるかどうかを確認する方法はありますか? そうでない場合はwhile-loop、プロセスが実際にすでに終了していることを発見し、ループを中断するまで続行する必要があります。

4

2 に答える 2

11

はい、select モジュールの pollを使用します。

import select
q = select.poll()
q.register(stdout,select.POLLIN)

そしてその間に次を使用します:

l = q.poll(0)
if not l:
    pass # no input
else:
    pass # there is some input
于 2011-06-27T08:50:05.393 に答える
2

select.poll()の回答は非常にきちんとしていますが、Windows では機能しません。次の解決策は代替手段です。stdout を覗くことはできませんが、readline() のノンブロッキングの代替手段を提供し、この回答に基づいています:

from subprocess import Popen, PIPE
from threading import Thread
def process_output(myprocess): #output-consuming thread
    nextline = None
    buf = ''
    while True:
        #--- extract line using read(1)
        out = myprocess.stdout.read(1)
        if out == '' and myprocess.poll() != None: break
        if out != '':
            buf += out
            if out == '\n':
                nextline = buf
                buf = ''
        if not nextline: continue
        line = nextline
        nextline = None

        #--- do whatever you want with line here
        print 'Line is:', line
    myprocess.stdout.close()

myprocess = Popen('myprogram.exe', stdout=PIPE) #output-producing process
p1 = Thread(target=process_output, args=(myprocess,)) #output-consuming thread
p1.daemon = True
p1.start()

#--- do whatever here and then kill process and thread if needed
if myprocess.poll() == None: #kill process; will automatically stop thread
    myprocess.kill()
    myprocess.wait()
if p1 and p1.is_alive(): #wait for thread to finish
    p1.join()

ノンブロッキング読み取りの他の解決策がここで提案されていますが、私にはうまくいきませんでした:

  1. readline を必要とするソリューション (Queue ベースのものを含む) は常にブロックされます。readline を実行するスレッドを強制終了することは困難 (不可能?) です。それを作成したプロセスが終了したときにのみ強制終了されますが、出力を生成するプロセスが強制終了されたときは強制終了されません。
  2. anonnn が指摘したように、低レベルの fcntl と高レベルの readline 呼び出しを混在させると、適切に機能しない可能性があります。
  3. select.poll() の使用はきちんとしていますが、Python ドキュメントによると、Windows では機能しません。
  4. サードパーティのライブラリを使用すると、このタスクにはやり過ぎのように見え、依存関係が追加されます。
于 2013-03-15T05:04:51.577 に答える