【问题标题】:Python subprocess interaction, why does my process work with Popen.communicate, but not Popen.stdout.read()?python子进程交互,为什么我的进程使用Popen.communicate,而不使用Popen.stdout.read()?
【发布时间】:2012-03-29 07:00:14
【问题描述】:

我正在尝试使用subprocess 模块与带有 Python 的命令行聊天机器人进行通信。 (http://howie.sourceforge.net/ 使用编译好的win32二进制,我有我的理由!)

这行得通:

proc = Popen('Howie/howie.exe', stdout=PIPE,stderr=STDOUT,stdin=PIPE)
output = proc.communicate()

但是Popen.communicate 等待进程终止(并将其发送 EOF?),我希望能够与之交互。对此的明显解决方案是像这样读取stdout / 写入stdin

这不起作用:

proc = Popen('Howie/howie.exe', stdout=PIPE,stderr=STDOUT,stdin=PIPE)
while True: print proc.stdout.readline()

(请注意,我实际上使用的是基于http://code.activestate.com/recipes/440554/ 的更复杂的代码,但问题是一样的。)

问题是,第二种方法非常适合与 cmd 通信,但是当我运行聊天机器人时,什么也没有。所以我的问题是,捕获输出与使用 Popen.communicate() 有何不同?

即我可以使用第二种方法照常使用命令行,直到我运行聊天机器人,此时我停止接收输出。使用第一种方法可以正确显示机器人的前几行输出,但我无法与之交互。

【问题讨论】:

    标签: python stdout popen subprocess


    【解决方案1】:

    两者之间的一个主要区别是,communicate() 在发送数据后关闭标准输入。我不知道你的具体情况,但在很多情况下,这意味着如果一个进程正在等待用户输入的结束,他会在使用communicate() 时得到它,而当代码阻塞时永远不会得到它read() 或 readline()。

    先尝试添加 Popen.stdin.close() 看看它是否会影响您的情况。

    【讨论】:

    • 谢谢你,关闭标准输入允许聊天机器人完全像 Popen.communicate 那样启动,尽管现在我遇到了我需要能够继续与之交谈的问题......
    • 也许您的应用程序正在逐行读取,在这种情况下,您可以只发送单行让它回复?您要完成的具体任务是什么?
    • 但是一旦标准输入被关闭,我如何发送输入?我希望能够逐行提交和接收
    • @SudoNhim:如果您想与进程进行双向通信,请考虑使用pexpect 而不是subprocess
    • 谢谢,我会调查的。刚刚找到了一个可能的解决方案;手动发送 EOF 字符(Python 中的“\x1a”)对程序具有与标准输入相同的效果,当然它使标准输入保持打开状态。然而,程序仍然在 EOF 字符上吐出假人。
    【解决方案2】:

    如果你想在发送 EOF 后与程序进行交互,而不是使用Popen.stdin.close(),你可以手动发送命令行文件结尾字符,效果相同但保持标准输入打开。

    在 Python 中,这个字符的转义序列是 '\x1a'

    【讨论】:

    • 这只适用于奇怪的 DOS/Windows 世界,它使用固定的^Z 作为 EOF 标记。在许多其他系统上,这通常是 ^D (\x04),但是它可以很容易地更改,不应该被依赖并且绝对不能在任何地方硬编码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 2013-01-05
    • 2016-12-15
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多