如何使用子进程和Popen从.exe获取所有输出?

2024-09-26 18:19:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图运行一个可执行文件并使用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                                          

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

所以我们可以看到一些线不见了。我必须写1并选择值后请选择下面的fule数字出现。

我试图使用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))

谢谢塞巴斯蒂安。我可以看到整个输出,但不能用当前代码输入任何输入。


Tags: 文件textimportstdinstdoutlinetoolspid
3条回答

你问题的缩进让我有点不舒服,因为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周围找找适合你的用途。

要将所有stdout作为字符串获取:

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在非交互模式下使用块缓冲,则在缓冲区刷新之前不会显示行。^{}模块可能能够更快地获得输出。

要将输出保存到文件:

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')

如果您与程序的交互更像是一个对话,而不是您可能需要的^{} module。这是一张example from ^{} 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之类的特殊键,您可能需要^{} module或其纯Python实现^{}。类似于:

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}
""")

它不捕获输出。

要将所有stdout作为字符串获取:

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添加到合并stdout/stderr的Popen()调用中。

注意:如果cmd在非交互模式下使用块缓冲,则在缓冲区刷新之前不会显示行。^{}模块可能能够更快地获得输出。

要将输出保存到文件:

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')

如果您与程序的交互更像是一个对话,而不是您可能需要的^{} module。这是一张example from ^{} 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之类的特殊键,您可能需要^{} module或其纯Python实现^{}。类似于:

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}
""")

它不捕获输出。

相关问题 更多 >

    热门问题