我正在尝试编写一个minecraft服务器包装器,它允许我发送命令并接收输出。最后,我将附加一个套接字接口,以便我可以远程控制我的家庭服务器以重启/第二个命令等。
为此,我试图使用python子进程模块启动服务器,然后发送命令并接收服务器的输出。现在,我遇到了一个问题,我可以抓住服务器的输出并将其反映到屏幕上,但是我发送给进程的第一个命令会冻结整个过程,我必须将其杀掉。 应该注意的是,我试图删除process.communicate行,而是用print(命令)替换它。这也冻结了这个过程我最基本的当前代码如下:
from subprocess import Popen, PIPE
from threading import Thread
import threading
def listen(process):
while process.poll() is None:
output = process.stdout.readline()
print(str(output))
def talk(process):
command = input("Enter command: ")
while command != "exit_wrapper":
#freezes on first send command
parse_command(process, command)
command = input("Enter command: ")
print("EXITTING! KILLING SERVER!")
process.kill()
def parse_command(process, command):
process.communicate(command.encode())
def main():
process = Popen("C:\\Minecraft Servers\\ServerStart.bat", cwd = "C:\\Minecraft Servers\\", stdout=PIPE, stdin=PIPE)
listener = Thread(None, listen, None, kwargs={'process':process})
listener.start()
talker = Thread(None, talk, None, kwargs={'process':process})
talker.start()
listener.join()
talker.join()
if __name__ == "__main__":
main()
非常感谢任何提供的帮助!
答案 0 :(得分:0)
subprocess.Popen.communicate()
文档明确指出:
与流程交互:将数据发送到stdin。从stdout和stderr读取数据,直到达到文件结尾。 等待进程终止。
在你的情况下,它正是这样做的。您想要做什么而不是等待进程终止是与进程交互所以,就像您直接在listen()
函数中读取STDOUT流一样,您应该写入进程STDIN命令发送命令。类似的东西:
def talk(process):
command = input("Enter command: ")
while command != "exit_wrapper" and process.poll() is None:
process.stdin.write(command) # write the command to the process STDIN
process.stdin.flush() # flush it
command = input("Enter command: ") # get the next command from user
if process.poll() is None:
print("EXITING! KILLING SERVER!")
process.kill()
然而,这种方法的问题在于,您可能会使用Enter command:
提示覆盖服务器的输出,并且用户最终会在服务器的输出上输入命令而不是'提示'你已经指定了。
您可能想要做的是在listen()
函数中解析服务器的输出,然后根据收集的输出确定包装服务器何时需要用户输入,然后只调用{{ 1}}函数(当然,从中删除while循环)以获取用户输入。
如果Minecraft服务器试图通过它告诉你一些东西,你也应该也管出STDERR。