Python调用Java程序时模拟输入内容未在输出中显示的问题
问题
我正在编写一个用于评分Hangman.java文件的Python脚本。该Java程序通过控制台要求用户猜测字母,正常运行时用户在控制台输入猜测内容即可。我用Python脚本通过输入文件(每行一个猜测内容)模拟用户输入,目前已成功将输入文件内容重定向到Java程序,并能保存Java程序的输出(用于与标准输出比对)。但存在问题:Python脚本模拟输入的字符未在Java程序的输出中显示,例如实际输出为:
Enter your next guess:
You guessed T.
而预期输出为:
Enter your next guess: T
You guessed T.
以下是我的Python脚本:
import subprocess import sys import os def run_java_with_input(java_file, input_file, output_file): subprocess.run(['javac', java_file + '.java'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) os.makedirs(os.path.dirname(output_file), exist_ok=True) with open(input_file, 'r') as inputs, open(output_file, 'w') as output: process = subprocess.Popen(['java', java_file], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) for line in inputs: process.stdin.write(line) process.stdin.flush() out, err = process.communicate() output.write(out) if __name__ == "__main__": run_java_with_input(sys.argv[1], sys.argv[2], sys.argv[3])
解决方案
问题核心原因:当Java程序的标准输入被重定向为管道时,操作系统不会自动回显输入内容到标准输出——而控制台交互时,系统会默认完成回显。因此需要在Python脚本中手动模拟这个回显行为。
修改思路
- 实时监听Java程序的输出,当检测到输入提示行时,先将提示行写入输出文件,再写入对应的输入内容(模拟控制台回显),最后把输入传给Java进程
- 启用行缓冲,确保能实时读取Java程序的输出,避免内容顺序混乱
修改后的脚本
import subprocess import sys import os def run_java_with_input(java_file, input_file, output_file): # 编译Java文件 subprocess.run(['javac', java_file + '.java'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) os.makedirs(os.path.dirname(output_file), exist_ok=True) with open(input_file, 'r') as inputs, open(output_file, 'w') as output: # 启动Java进程,设置行缓冲保证实时读取输出 process = subprocess.Popen( ['java', java_file], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1 ) # 提前读取所有输入行,按顺序匹配输入提示 input_lines = [line.rstrip('\n') for line in inputs] input_idx = 0 # 实时读取输出并处理输入 while True: output_line = process.stdout.readline() if not output_line and process.poll() is not None: break # 写入Java程序的输出到文件 output.write(output_line) output.flush() # 检测到输入提示时,写入输入内容并回显 if "Enter your next guess:" in output_line: if input_idx < len(input_lines): guess = input_lines[input_idx] # 模拟控制台回显输入内容 output.write(f"{guess}\n") output.flush() # 将输入传给Java进程 process.stdin.write(f"{guess}\n") process.stdin.flush() input_idx += 1 # 处理进程结束后的剩余输出 remaining_output = process.communicate()[0] if remaining_output: output.write(remaining_output) if __name__ == "__main__": run_java_with_input(sys.argv[1], sys.argv[2], sys.argv[3])
关键修改点
- 设置
bufsize=1启用行缓冲,确保实时读取Java程序的输出行 - 按顺序匹配输入提示和输入内容,保证输出顺序与控制台交互一致
- 手动回显输入内容到输出文件,还原控制台交互时的输出格式
内容的提问来源于stack exchange,提问作者meep
相关产品推荐
相关产品推荐

