subprocess.Popen() 的 stdin 问题

1 投票
2 回答
4052 浏览
提问于 2025-04-16 16:16
import subprocess
import threading
import StringIO

class terminal(threading.Thread):
    def run(self):
        self.prompt()

    def prompt(self):
        x = True
        while x:
            command = raw_input(':')
            x = self.interpret(command)

    def interpret(self,command):
        if command == 'exit':
            return False
        else:
            print 'Invalid Command'
        return True

class test(threading.Thread):
    command = 'java -jar ../bukkit/craftbukkit.jar'
    test = StringIO.StringIO()
    p = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while (p.poll() == None):
        line = p.stderr.readline()
        if not line: break
        print line.strip()

term = terminal()
testcl = test()
term.start()
testcl.start()

这个程序运行没有错误,但是在运行时你无法在提示符下输入任何内容。用户输入的字符或者回车都看不见,但运行的jar文件的输出会打印出来。我希望这个程序能在终端类中接收输入,处理这些输入,然后把结果输出到正在运行的Java程序中。我在网上查了很多资料,只找到subprocess.Popen(),但是我搞不清楚标准输入、输出和错误的重定向。请问我该如何用Popen解决这个问题,或者有没有其他完全不同的方法?

2 个回答

0

我最后解决问题的方法是按照AJ的建议,修改了while循环

while x:
    select.select((sys.stdin,),(),())
    a = sys.stdin.read(1)
    if not a == '\n':  
        sys.stdout.write(a)
        sys.stdout.flush()
    else:
        x = self.interpret(command)

还修改了Popen的调用方式

p = subprocess.Popen(command, shell=False, stdin = subprocess.PIPE)

我还需要把shell=True这个参数改掉。即使我改了循环,这个简单的参数还是把一切搞坏了

0

这里有一个类似的问题:

Python和子进程输入管道

在这个情况下,提问者也是在运行一个Java虚拟机(jvm),并且期待用户输入。我认为你可以用一个调用 select((sys.stdin,),(),()) 来替代你的while循环。当 select() 返回时,你应该能从它的返回值中读取输入,然后把这些输入传递给你的 Popen 对象。

撰写回答