【问题标题】:'Communicate' in Python does not workPython中的“沟通”不起作用
【发布时间】:2026-01-17 14:40:01
【问题描述】:

我正在尝试编写一个 python 程序来测试一个使用 Scanner 从标准输入获取输入的 java 程序。

所有其他帖子都指向使用与 popen 通信,但对我来说它绝对不起作用。当我运行我的python程序时,它只是调用popen,然后在java程序等待输入时停止。我在popen后写了一个打印语句来检查。它从不打印。

它非常简单。我只是想给这个等待输入的程序一些输入。

代码如下:

import os.path, subprocess
from subprocess import PIPE

p = subprocess.Popen(['java', 'Main'], stdin=PIPE, stdout=PIPE)
print 'after subprocess' #this never get's printed
output = p.communicate(input='5 5 4 3 2 1'.encode())[0]
print output

【问题讨论】:

  • 如果您将打印更改为“assert False”之类的内容,您会看到回溯吗?根据您的呼叫正在做什么,通信呼叫可能不会立即返回,但 Popen 应该。这对我有用: p = subprocess.Popen(['xargs'], stdin=PIPE, stdout=PIPE);打印 p.communicate(input='hello')
  • 他可能看不到after subprocess 的原因是它可能在标准输出的缓冲区中。 (sys.stdout.flush() 会解决这个问题。)或者它甚至可能在他用来查看输出的任何东西的 input 缓冲区中,如果他不只是在命令行上运行它的话。无论如何,在他使用 ^C 或其他任何方式终止程序后,输出应该是可见的,但可能与丑陋的回溯混合在一起。
  • 不相关:不要在字节串上调用.encode()print output 语句表明您正在使用 Python 2。
  • Popen() 不等待子进程退出。在您的情况下,它不太可能长时间阻塞。如果您在print 'after subprocess' 之后添加sys.stdout.flush(),那么您应该会看到该消息。

标签: java python subprocess popen communicate


【解决方案1】:

如果没有更多信息(例如一些示例 Java 代码),很难确定,但我敢打赌,问题是 Java 代码正在等待完整的一行,而您还没有发送。

如果是这样,修复很简单:

output = p.communicate(input='5 5 4 3 2 1\n'.encode())[0]

附带说明一下,您究竟为什么要在该字符串上调用encode?它已经以您的源代码使用的任何字符集进行编码。因此,当您调用encode 时,它必须首先将其解码 为Unicode。然后,因为您没有将参数传递给 encode,它会将其编码为您的默认字符集 (sys.getdefaultencoding()),这似乎与 Java 代码所期望的相比不太可能匹配你已经拥有了。几乎不值得用参数调用 encode,而且您几乎应该*永远不要在 str 上调用它,而只在 unicode 上调用它。

* 如果您想知道,例外情况是您使用少数特殊编解码器,例如 hexgzip。在 Python 3 中,他们认为这些特殊情况的偶尔有用性远不及在已编码的字符串上调用 encode 的频繁错误磁铁,因此他们将其从语言中删除。

【讨论】:

  • 非常感谢!那行得通。我正在使用编码,因为我在另一个通信示例中看到了它,我认为这可能是问题所在。我按照你的建议拿出来了
  • @bgenchel:不要只是随机调用方法而不了解它们的作用。那永远无法解决任何问题。充其量,它使您的代码在一个特定的测试用例上工作,但在下一个测试用例上以更难调试的方式失败。
  • 不接受 EOF 而不是 '\n' 的 Java 代码似乎已损坏。不要在此处使用 .encode() (Python 2)。
  • @JFSebastian:这是一个很好的观点,特别是因为他的目标是测试 Java 代码,所以测试它的输入处理是否符合规范(必须有一个规范;Java 代码总是有一个规范,对吧?)似乎值得做。 (对于您评论的后半部分,我已经在答案中解释了这一点。)
最近更新 更多