如何运行Python解释器并使用Java获取其输出?

如何运行Python解释器并使用Java获取其输出?,java,python,Java,Python,是否可以使用Java从Python获取控制台输出?以下是此类输出的示例: Python 3.3.4 (v3.3.4:7ff62415e426, Feb 10 2014, 18:13:51) [MSC v.1600 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> 2+2 4 >>> 现在,主要目标是通过使用Ja

是否可以使用Java从Python获取控制台输出?以下是此类输出的示例:

Python 3.3.4 (v3.3.4:7ff62415e426, Feb 10 2014, 18:13:51) [MSC v.1600 64 bit (AMD64)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 2+2
4
>>>
现在,主要目标是通过使用Java调用Python解释器来获得上述输出。以下是我的尝试:

//...
//Irrelevant code omitted

ProcessBuilder processBuilder = new ProcessBuilder("cmd");
processBuilder.redirectErrorStream(true);
processBuilder.start();
processBuilder.command("python2");
Process pythonProcess = processBuilder.start();
OutputStream outputStream = pythonProcess.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(outputStream);
osw.write("2+2\r\nquit()\r\n");
osw.flush();
osw.close();
InputStream inputStream = pythonProcess.getInputStream();
BufferedReader bufferedReader = new BufferedReader(
                  new InputStreamReader(inputStream));
String line;

while( (line=bufferedReader.readLine())!=null) {

    System.out.println(line);

}

//...
//Irrelevant code omitted
我知道调用
start
方法会产生一个新的进程及其执行环境。将
python2
写入进程的输出流会导致创建另一个进程。这就是问题开始的时候。我无法找到将命令
2+2
发送到Python解释器(CMD的子进程)而不是其父进程的方法


总结:如何运行Python解释器,在解释器中执行一些命令,最后将结果打印到标准输出?

Python可执行文件可以告诉您正在运行命令 非交互的。一旦它意识到正在以非交互方式运行它 不再尝试与你互动;为什么要麻烦打印到 如果没有人的话,从stdin读取或读取数据

要确认这是真的,您可以尝试运行例如“ls”或“ps”和 确保它们在您的程序中工作,然后运行例如“ftp”或“telnet” 或者“python”,看到它不工作,什么也不输出

用Linux的说法,问题在于我们的运行方式 进程不向其附加TTY。解决办法是欺骗他们 通过创建一个PTY来相信另一端有一个TTY

关于:

  • 我的Mac OS X 10.9.4笔记本电脑,带有CPython 2.7.5和Java 1.8.0_05和
  • Ubuntu12.04.4LTS服务器,带有CPython2.7.5和Java1.7.055
以下作品,尽管风格非常丑陋:

导入java.io.BufferedReader;
导入java.io.BufferedWriter;
导入java.io.InputStream;
导入java.io.InputStreamReader;
导入java.io.IOException;
导入java.io.OutputStream;
导入java.io.OutputStreamWriter;
福班{
公共静态void main(字符串[]args)引发IOException、InterruptedException{
// https://stackoverflow.com/questions/1401002/trick-an-application-into-thinking-its-stdin-is-interactive-not-a-pipe
// 
//使用脚本或取消缓冲是一个重要的问题
//步骤:您不能在Python中交互使用stdin,即使在
//python-u。至少脚本随Linux/MacOSX一起提供,但是
//解除缓冲也很好。
ProcessBuilder pb;
开关(System.getProperty(“os.name”)){
案例“Mac OS X”:
pb=新ProcessBuilder(
“/usr/bin/script”、“-q”、“/dev/null”、“/usr/bin/python”);
打破
违约:
//Linux
pb=新ProcessBuilder(
“/usr/bin/script”、“-qfc”、“/usr/bin/python”、“/dev/null”);
}
//这没什么区别。
//pb.重定向错误流(真);
进程p=pb.start();
char[]readBuffer=新字符[1000];
InputStreamReader isr=新的InputStreamReader(p.getInputStream());
BufferedReader br=新的BufferedReader(isr);
int字符数;
布尔值=假;
while(true){
如果(!br.ready()&&!write){
//丑陋。应该先读取“>>>”提示,然后再写入。
睡眠(1000);
如果(!写入){
书面=真实;
OutputStream os=p.getOutputStream();
OutputStreamWriter osw=新的OutputStreamWriter(os);
BufferedWriter bw=新的BufferedWriter(osw);
写(“2+2”);
换行符();
write(“quit()”);
换行符();
bw.flush();
bw.close();
}
继续;
}
charCount=br.read(readBuffer);
如果(字符数>0)
System.out.print(新字符串(readBuffer,0,charCount));
其他的
打破
}
}
}
我不会这样做的。相反,我会使用线程来保持交互 并避免阻塞读取,执行expect所做的操作,即等待 在写之前要有一些提示。在上面的代码中,我盲目地睡觉 那就抱最好的希望吧

但是我注意到您正在使用Windows,因为您已经运行了“cmd”。 对不起,我不知道如何在Windows上创建PTY。不过我想 你可以得到预期的Windows;unbuffer是其中的一个实用程序 期望:

或者试试cygwin,但我还没有测试过

有关TTY和PTY的更多背景信息,请参阅:


来自Asim Ihsan的答案有正确的根本原因-python将知道它没有连接到交互式终端,并且没有按照您想要的方式运行。但是,在启动python时,通过传递
-i
标志,可以使python以交互模式运行。这比Asim建议的要简单。您应该直接启动python(不需要先启动
cmd
)。您将使用类似于

ProcessBuilder pb = new ProcessBuilder('python', '-i');

然后大致按照原问题进行。启动进程,获取相关的流,并对流进行读写。

您的方法不容易实现,但多线程也可能实现。我认为使用可能会更容易。@ElliottFrisch:你能用几句话解释一下为什么我的代码不能按预期工作吗?你还没有找到将命令2+2发送给Python解释器的方法。不要运行
cmd
,只运行
python2
。添加线程。或者使用jython。或者在这里添加更多关于为什么希望能够控制
cmd
来控制子流程的详细信息。提示,我不认为你可以。@ElliottFrisch:我试图直接运行
python2
,但没有得到任何输出。很抱歉打扰你,你为什么要这样做