Python: 使用subprocess模块无法读写其他命令行应用程序
我在Windows上使用Python 3.0,想要自动化测试一个命令行应用程序。用户可以在这个应用程序中输入命令,然后它会返回两个XML数据包的输出。一个是发送的数据包,另一个是接收的数据包。通过分析这些数据包,我可以验证结果。我的代码如下:
p = subprocess.Popen(SomeCmdAppl, stdout=subprocess.PIPE,
shell = True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
p.stdin.write((command + '\r\n').encode())
time.sleep(2.5)
testresult = p.stdout.readline()
testresult = testresult.decode()
print(testresult)
但是我没有得到任何输出。程序在我尝试使用readline()读取输出的地方卡住了。我试过read(),结果也是卡住。
当我手动运行这个命令行应用程序并输入命令时,我能正确地得到两个XML数据包的输出,如下所示:
Sent: <PivotNetMessage>
<MessageId>16f8addf-d366-4031-b3d3-5593efb9f7dd</MessageId>
<ConversationId>373323be-31dd-4858-a7f9-37d97e36eb36</ConversationId>
<SageId>4e1e7c04-4cea-49b2-8af1-64d0f348e621</SagaId>
<SourcePath>C:\Python30\PyNTEST</SourcePath>
<Command>echo</Command>
<Content>Hello</Content>
<Time>7/4/2009 11:16:41 PM</Time>
<ErrorCode>0</ErrorCode>
<ErrorInfo></ErrorInfo>
</PivotNetMessagSent>
Recv: <PivotNetMessage>
<MessageId>16f8addf-d366-4031-b3d3-5593efb9f7dd</MessageId>
<ConversationId>373323be-31dd-4858-a7f9-37d97e36eb36</ConversationId>
<SageId>4e1e7c04-4cea-49b2-8af1-64d0f348e621</SagaId>
<SourcePath>C:\PivotNet\Endpoints\Pipeline\Pipeline_2.0.0.202</SourcePath>
<Command>echo</Command>
<Content>Hello</Content>
<Time>7/4/2009 11:16:41 PM</Time>
<ErrorCode>0</ErrorCode>
<ErrorInfo></ErrorInfo>
</PivotNetMessage>
但是当我使用communicate()时,我只收到了发送的数据包,却没有收到接收的数据包。为什么我会缺少接收的数据包呢?communicate(0应该能从标准输出中获取所有内容,对吧?
p = subprocess.Popen(SomeCmdAppl, stdout=subprocess.PIPE,
shell = True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
p.stdin.write((command + '\r\n').encode())
time.sleep(2.5)
result = p.communicate()[0]
print(result)
有没有人能给我一个可以工作的示例代码?我不知道是否需要在不同的线程中进行读写。请帮帮我。我需要进行重复的读写操作。Python中有没有什么高级模块可以使用?我觉得Pexpect模块在Windows上不太好用。
3 个回答
0
你有没有想过用pexpect来代替subprocess呢?pexpect可以处理一些细节问题,这些问题可能是导致你的代码无法正常工作的原因(比如缓冲区的刷新等)。虽然它可能还不支持Python 3,但在Python 2.x中运行得很好。
0
试着用 communicate
来发送你的输入,而不是用 write
:
result = p.communicate((command + '\r\n').encode())[0]
1
这是一个很常见的问题,比如你可以看看:
- 如何通过Python与Windows控制台应用程序互动
- 如何从Python的subprocess.Popen中获取“实时”信息(2.5版)
- 如何读取subprocess.stdout管道中当前的所有内容并返回?
(其实,你在提问的时候应该已经看到这些了...?!)
我有两个想法:
- p.stdin.write((command + '\r\n').encode()) 这个操作也是缓冲的,所以你的子进程可能根本没有看到它的输入。你可以尝试刷新这个管道。
- 在其他问题中,有人建议在子进程上使用stdout.read()而不是readline(),并且要读取适量的字符。你可以试着实验一下这个方法。
把你的结果发出来吧。