python subprocess - 如何检查PIPE中是否有新数据?

时间:2012-04-19 21:45:40

标签: python subprocess popen readline eof

我有以下示例:

import subprocess

p = subprocess.Popen("cmd",stdin = subprocess.PIPE, stdout=subprocess.PIPE )
p.stdin.write(b'cd\\' + b'\r\n')
p.stdin.write(b'dir' + b'\r\n')
p.stdin.write(b'\r\n')



while True:
    line = p.stdout.readline()
    print(line.decode('ascii'), end='')
    if line.rstrip().decode('ascii') == 'C:\>': #I need to check at this point if there is new data in the PIPE
        print('End of File')
        break

我正在收听来自子流程输出的PIPE,如果没有任何新数据通过PIPE,我想停止阅读。我想有一个控制语句告诉我PIPE是空的。这有助于我避免在我的进程冻结或以意外结果结束时出现的问题。

1 个答案:

答案 0 :(得分:1)

除非进程结束或者您希望停止读取信号,否则没有好的方法可以提前知道管道中是否有数据,因为命令只会在达到数字时终止您要读取的字节数[.read(n)],到达换行符[.readline()],或到达文件的末尾(在该过程结束之前不存在)。

但是,您不需要运行cmd.exe来运行程序,因为您的程序已经在cmd shell中运行。

我建议您使用subprocess直接调用程序,并在代码中处理exceptions / return_code。你可以做点像......

import subprocess
import time

p = subprocess.Popen("your_program.exe",
                     "-f", "filename",
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE)

# If you have to use stdin, do it here.
p.stdin.write('lawl here are my inputs\n')

run_for = 0
while p.poll() == None:
    time.sleep(1)
    if run_for > 10:
        p.kill()
        break
    run_for += 1

if p.return_code == 0:
    ...handle success...
else:
    ...handle failure...

您可以在循环中执行此操作并启动将运行下一个文件的新进程。

如果启动程序 花费很多(如果它现在不再停止阅读,因为它会让人感到尴尬)那么也许(这是一个彻头彻尾的黑客,但是)在你的过程之后已经运行了一段时间,你可以将一个特别奇怪但无害的字符串传递给p.stdin,就像p.stdin.write("\n~%$%~\n")一样。

如果你能侥幸逃脱,那么你可以做点像......

for line in p.stdout.readlines():
    if '~%$%~' in line:
        break

但是,废话,请不要这样做。这是一个黑客攻击。