【问题标题】:How do I get all of the output from my .exe using subprocess and Popen?如何使用子进程和 Popen 从我的 .exe 获取所有输出?
【发布时间】:2012-09-18 00:42:37
【问题描述】:

我正在尝试运行一个可执行文件并使用subprocess.Popen 捕获其输出;但是,我似乎没有得到所有的输出。

import subprocess as s
from subprocess import Popen 
import os

ps = Popen(r'C:\Tools\Dvb_pid_3_0.exe', stdin = s.PIPE,stdout = s.PIPE)
print 'pOpen done..'

while:

line = ps.stdout.readline()
print line

手动打开时比原来的exe文件少打印两行。

我尝试了另一种方法,结果相同:

f = open('myprogram_output.txt','w')
proc = Popen('C:\Tools\Dvb_pid_3_0.exe ', stdout =f)

line = proc.stdout.readline()
print line
f.close()

谁能帮我获取exe的完整数据?

按照塞巴斯蒂安的要求:

原始exe文件最后几行o/p:

-Gdd : 通用计数 (1 - 1000)

-Cdd : 剪切开始于 (0 - 99) -Edd : 在 (1 - 100) 处截断

请在下方选择流文件号:

1 - .\pdsx100-bcm7230-squashfs-sdk0.0.0.38-0.2.6.0-prod.sao.ts

运行后得到的o/p:

-P0xYYYY      : Pid been interested                                          

-S0xYYYY : 对服务 ID 感兴趣
-T0xYYYY : 对传输 ID 感兴趣
-N0xYYYY : 感兴趣的网络 ID
-R0xYYYY : 旧的 Pid 已被此 PID 替换
-Gdd : 通用计数 (1 - 1000)

所以我们可以看到缺少一些行。请选择下面出现的完整数字后,我必须写1并选择值。

我尝试使用 ps.stdin.write('1\n')。它没有打印exe文件中的值

新代码:

#!/usr/bin/env python
from subprocess import Popen, PIPE

cmd = r'C:\Tools\Dvb_pid_3_0.exe'
p = Popen(cmd, stdin=PIPE, stdout=None, stderr=None, universal_newlines=True)
stdout_text, stderr_text = p.communicate(input="1\n\n")

print("stdout: %r\nstderr: %r" % (stdout_text, stderr_text))
if p.returncode != 0:
    raise RuntimeError("%r failed, status code %d" % (cmd, p.returncode))

谢谢塞巴斯蒂安。我能够看到整个输出,但无法使用当前代码输入任何输入。

【问题讨论】:

  • 有问题的两行是什么?你确定他们发送到stdout 而不是stderr 吗?
  • 您的第一个示例中的错字,while 之后的缩进,或者您的代码真的是这样吗?
  • @cdarke,是的,错字是真的:在编辑时它被删除了

标签: python windows subprocess popen


【解决方案1】:

你的问题的缩进让我有点失望,因为 Python 对此很特别。你有没有尝试过这样的事情:

import subprocess as s
from subprocess import Popen 
import os

ps = Popen(r'C:\Tools\Dvb_pid_3_0.exe', stdin = s.PIPE,stdout = s.PIPE)
print 'pOpen done..'

(stdout, stderr) = ps.communicate()
print stdout

我认为stdout 将是您从命令返回的任何内容的一个字符串,因此这可能不是您想要的,因为readline() 假定您想逐行查看输出。

建议在http://docs.python.org/library/subprocess.html 附近寻找一些符合您需要的用途。

【讨论】:

  • 您好,感谢您的回复,但代码在执行后只是在等待。
【解决方案2】:

将所有标准输出作为字符串获取:

from subprocess import check_output as qx

cmd = r'C:\Tools\Dvb_pid_3_0.exe'
output = qx(cmd)

将 stdout 和 stderr 作为单个字符串获取:

from subprocess import STDOUT

output = qx(cmd, stderr=STDOUT)

将所有行作为一个列表:

lines = output.splitlines()

获取子进程正在打印的行:

from subprocess import Popen, PIPE

p = Popen(cmd, stdout=PIPE, bufsize=1)
for line in iter(p.stdout.readline, ''):
    print line,
p.stdout.close()
if p.wait() != 0:
   raise RuntimeError("%r failed, exit status: %d" % (cmd, p.returncode))

stderr=STDOUT 添加到Popen() 调用以合并stdout/stderr。

注意:如果cmd 在非交互模式下使用块缓冲,则在缓冲区刷新之前不会出现行。 winpexpect 模块或许能更快得到输出。

将输出保存到文件:

import subprocess

with open('output.txt', 'wb') as f:
    subprocess.check_call(cmd, stdout=f)

# to read line by line
with open('output.txt') as f:
    for line in f:
        print line,

如果cmd 总是需要输入,即使是空的;设置stdin:

import os

with open(os.devnull, 'rb') as DEVNULL:
    output = qx(cmd, stdin=DEVNULL) # use subprocess.DEVNULL on Python 3.3+

您可以组合这些解决方案,例如,合并 stdout/stderr,并将输出保存到文件,并提供空输入:

import os
from subprocess import STDOUT, check_call as x

with open(os.devnull, 'rb') as DEVNULL, open('output.txt', 'wb') as f:
    x(cmd, stdin=DEVNULL, stdout=f, stderr=STDOUT)

要将所有输入作为单个字符串提供,您可以使用.communicate() 方法:

#!/usr/bin/env python
from subprocess import Popen, PIPE

cmd = ["python", "test.py"]
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
stdout_text, stderr_text = p.communicate(input="1\n\n")

print("stdout: %r\nstderr: %r" % (stdout_text, stderr_text))
if p.returncode != 0:
    raise RuntimeError("%r failed, status code %d" % (cmd, p.returncode))

test.py:

print raw_input('abc')[::-1]
raw_input('press enter to exit')

如果您与该程序的互动更像是一场对话,而不是您可能需要winpexpect module。这是example from pexpect docs

# This connects to the openbsd ftp site and
# downloads the recursive directory listing.
from winpexpect import winspawn as spawn

child = spawn ('ftp ftp.openbsd.org')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('noah@example.com')
child.expect ('ftp> ')
child.sendline ('cd pub')
child.expect('ftp> ')
child.sendline ('get ls-lR.gz')
child.expect('ftp> ')
child.sendline ('bye')

要在 Windows 上发送 F3F10 等特殊密钥,您可能需要 SendKeys module 或其纯 Python 实现 SendKeys-ctypes。比如:

from SendKeys import SendKeys

SendKeys(r"""
    {LWIN}
    {PAUSE .25}
    r
    C:\Tools\Dvb_pid_3_0.exe{ENTER}
    {PAUSE 1}
    1{ENTER}
    {PAUSE 1}
    2{ENTER}
    {PAUSE 1}
    {F3}
    {PAUSE 1}
    {F10}
""")

它不捕获输出。

【讨论】:

  • from subprocess import check_output as qx qx 代表什么?
  • x eXecute,q 引用:bash 中的 origin `` 反引号,perl 中的 qx'' 运算符。
  • 嗨 Sebastian, 非常感谢您花时间和精力提供答案。我尝试了您的脚本 1)获取子进程打印的行,2)将输出保存到文件中。两个脚本都给了我与以前相同的响应,但少了两行。无法理解如何使用您的脚本编写输入。您能否解释一下.. 再次感谢
  • @Ajith:您是否尝试过stderr=STDOUT,如第二个示例所示?这两条缺失的行是否类似于密码提示(它们可能直接写入控制台(在标准输出、标准错误之外))?您想一次提供所有输入并读取程序的整个输出,还是交互更像是对话(来回)?输入/输出有多大? Update your question with the info。如果您希望我收到通知,可以发表评论。
  • 第二个例子。该脚本只是在执行后等待某些内容。键盘中断后的错误消息-C:\Tools>python DVB.py Traceback(最近一次调用最后):文件“DVB.py”,第 16 行,在 输出 = qx( cmd, stderr=STDOUT) 文件“C:\Python27\lib\subprocess.py”,第 538 行,在 check_output 输出中,未使用_err = process.communicate() 文件“C:\Python27\lib\subprocess.py”,第 746 行,在通信 stdout = _eintr_retry_call(self.stdout.read) 文件“C:\Python27\lib\subprocess.py”,第 478 行,在 _eintr_retry_call return func(*args) KeyboardInterrupt
猜你喜欢
  • 2020-07-05
  • 1970-01-01
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 2012-10-02
  • 2011-11-30
  • 2020-03-03
  • 2019-04-26
相关资源
最近更新 更多