在子进程中提供输入并打印输入和输出(Python 运行 Java)

问题描述 投票:0回答:1

我想使用python执行这个java程序

import java.util.Scanner;
public class Input {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter a number = ");
        int n = sc.nextInt();
        System.out.println("Number entered = "+n);
   }
}

我正在接受扫描仪输入,并且不想使用 (String[] args) 接受参数。

我尝试使用

import subprocess
myInput = '1'
subprocess.run( [ 'java', 'Input.java' ], input=myInput.encode() )

对于这个Python代码,终端中的输出是

Enter a number = Number entered = 1

但我想要的输出是

Enter a number = 1
Number entered = 1

这个问题类似于 input to C++executable python subprocess使用子进程捕获输入和输出(Python 运行 java) 但没有可行的解决方案。现在有合适的解决方案吗?

python java subprocess
1个回答
2
投票

这个答案太旧了,现在有asyncio.subprocess,它可以进行异步读写,但你需要知道asyncio和协程是如何工作的。


问题是没有独立于平台的方法可以做到这一点,因此如果您在 Linux 上,您可以将进程 stdout 设置为非阻塞并安全地从中读取,但在 Windows 上这是不可能的,因此有 3 种解决方法。

  1. 修改java文件打印“ “在问题和接收者在不同的行回答之后,Python 进程可以从标准输出
    readline
  2. 提前知道您想要读取多少个字母,就像您正在使用套接字一样。
  3. 使用线程

此解决方案通过将 stdin 和 stdout 写入另一个缓冲区进行临时存储来实现第二个选项。

import subprocess
import io


out_buff = io.StringIO()
with subprocess.Popen(['java', 'Input.java'],
                      stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,
                      text=True) as proc:

    out_buff.write(proc.stdout.read(17))
    in_val = "1\n"
    out_buff.write(in_val)
    proc.stdin.write(in_val)
    proc.stdin.flush()  # required
    out_buff.write(proc.stdout.read())

print(out_buff.getvalue())

out_buff.close()
Enter a number = 1
Number entered = 1

显然,如果您在回答之前期望某个关键字,您可以继续从标准输出中逐个字母地读取,直到您知道必须输入一些内容,但是如果您想要读取的内容超出了实际的范围,那么您的应用程序将被阻止。 避免阻塞的一个选项是使用线程,这个答案展示了如何做到这一点,但它变得很复杂。

编辑:仅使用 1 个额外线程即可显示第三个选项,但您必须延迟

import subprocess
import io
import threading
import time

def read_from_stdout(buffer,handle):
    try:
        while True:
            buffer.write(handle.read(1))
    except ValueError as e: # when reading from closed file
        pass

out_buff = io.StringIO()
with subprocess.Popen(['java', 'Input.java'],
                      stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,
                      text=True) as proc:

    thread = threading.Thread(target=read_from_stdout,args=(out_buff,proc.stdout))
    thread.start()
    time.sleep(0.1)  # wait for stdout to be read
    in_val = "1\n"
    out_buff.write(in_val)
    proc.stdin.write(in_val)
    proc.stdin.flush()  # required
    time.sleep(0.1)  # wait for stdout to be read

print(out_buff.getvalue())

out_buff.close()
© www.soinside.com 2019 - 2024. All rights reserved.