【问题标题】:Supplying input in subprocess and print the inputs along with the outputs (Python running Java)在子进程中提供输入并将输入与输出一起打印(运行 Java 的 Python)
【发布时间】:2022-11-11 00:16:48
【问题描述】:

我想用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 subprocessCapturing INPUT and output with subprocess (Python running java) 但没有可行的解决方案。现在有合适的解决方案吗?

【问题讨论】:

  • 我不做python,但本质上Java应用程序是从stdin读取的,所以你需要将stdin通过管道传输到子进程中
  • 是的,我试过但没有用。提供的发送链接存在问题。

标签: python java subprocess


【解决方案1】:

问题是没有独立于平台的方法来做到这一点,所以如果你在 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
    "
        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
    

    显然,如果您在回答之前期望某个关键字,您可以继续从标准输出逐个字母地阅读,直到您知道您必须输入一些内容,但如果您想阅读的内容超出您的实际阅读范围,那么您的应用程序将被阻塞。 避免阻塞的一个选项是使用线程和this answer shows how to do so,但它会变得复杂。

    编辑:仅使用 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
    "
        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()
    

【讨论】:

  • 起初,它不起作用,但改变了它起作用的 time.sleep() 值......!
  • 问题是“java程序正在计算”和“java程序正在等待输入”之间没有区别,所以你唯一能做的就是等待足够的时间,遗憾的是没有信号说“我在等你输入”,除非您每隔几毫秒解析一次 out_buff 中的内容。
  • subprocess 模块包含 iosubprocess.io 的别名,您可以避免额外的导入
猜你喜欢
  • 2011-05-15
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 2019-12-05
  • 1970-01-01
  • 2017-09-21
  • 2013-05-31
相关资源
最近更新 更多