我正在监视和Minecraft服务器,我正在使用Python创建一个安装文件。我需要能够运行两个线程,一个在控制台窗口中运行minecraft_server.jar,而另一个线程不断检查minecraft_server的输出。另外,在启动Java进程后,如何从Python输入控制台?
示例:
thread1 = threading.Thread(target=listener)
thread2 = minecraft_server.jar
def listener():
if minecraft_server.jarOutput == "Server can't keep up!":
sendToTheJavaProccessAsUserInputSomeCommandsToRestartTheServer
答案 0 :(得分:2)
这里很难说,但我想你问的是如何:
最后一个很容易;事实上,你大部分时间都在编写它,你只需要在某处添加thread1.start()
。
subprocess
模块允许您启动程序并控制其输入和输出。如果您想立即输入所有输入,等待它完成,然后处理所有输出,这是最简单的,但显然这不是你的情况,所以它涉及更多:
minecraft = subprocess.Popen(['java', 'path/to/minecraft_server.jar', '-other', 'args],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
我将stdout和stderr合并成一个管道;如果你想单独阅读它们,或者将stderr发送到/ dev / null,或者其他什么,请参阅文档;这一切都非常简单。虽然我们在这里做出假设,但我将假设minecraft_server
使用简单的基于行的协议,其中每个命令,每个响应和每个信息消息恰好是一行(即,低于1K)以\n
开头的文字。
现在,要发送输入,您只需执行此操作:
minecraft.stdin.write('Make me a sandwich\n')
或者,在Python 3.x中:
minecraft.stdin.write(b'Make me a sandwich\n')
要阅读其输出,请执行以下操作:
response = minecraft.stdout.readline()
这就像普通文件一样。但请注意,它的工作方式类似于二进制文件。在Python 2.x中,唯一的区别是换行不会自动转换,但在Python 3.x中,这意味着您只能编写bytes
(和兼容的对象),而不是str
s ,您将收到bytes
返回。这有很好的理由,但是如果您希望获得与文本文件类似的管道,请参阅Frequently Used Arguments和Popen
Constructor下的universal_newlines
(以及可能的bufsize
)参数
此外,它的工作方式类似于阻止文件。对于常规文件,这很少重要,但是使用管道,很可能以后会有数据,但还没有数据(因为服务器还没有编写它)。所以,如果还没有输出(或者不是完整的行,因为我使用了readline()
),你的线程就会阻塞,等到有。
如果您不想这样,您可能想要创建另一个线程来为stdout提供服务。它的功能实际上看起来与你所拥有的相似:
def listener():
for line in minecraft.stdout:
if line.strip() == "Server can't keep up!":
minecraft.stdin.write("Restart Universe\n")
现在该线程可以整天阻塞并且没有问题,因为你的其他线程仍在继续。
好吧,不是没有问题。
首先,很难干净地关闭你的程序。
更严重的是,流程之间的管道具有固定的大小;如果你没有足够快地为stdout提供服务,或者孩子没有足够快地服务stdin,那么管道就会阻塞。而且,我写的东西的方式,如果stdin管道阻塞,我们将永远被stdin.write
阻止,并且不会进入下一次读取stdout
,所以这也可以阻止,突然间我们都在一起等待。
您可以通过另一个线程来为stdout提供服务来解决这个问题。 subprocess
模块本身包含所有高级函数使用的Popen._communicate
函数中的示例。 (确保查看Python 3.3或更高版本,因为早期版本存在错误。)
如果您使用的是Python 3.4+(或3.3,带有PyPI的backport),您可以改为使用asyncio
围绕事件循环重写程序,并按照您的方式处理输入和输出写一个基于反应堆的网络服务器。这就是所有酷孩子在2017年所做的事情,但是在2014年底,许多人仍然认为它看起来很新而且很可怕。
如果所有这些听起来比你签署的工作要多得多,你可能要考虑使用pexpect
,它包含了很多繁琐的细节,并做了一些可能的简化假设在你的情况下是真的。