繁体   English   中英

Python子流程因交互而挂起

[英]Python subprocess hangs on interaction

我正在尝试编写一个我的世界服务器包装器,使我可以向它发送命令并接收输出。 最终,我将附加一个套接字接口,以便可以远程控制我的家庭服务器以重新启动/第二个命令/等等。

为此,我尝试使用python子进程模块启动服务器,然后发送命令并接收服务器的输出。 现在,我遇到了一个问题,我可以获取服务器的输出并将其反映到屏幕上,但是我发送给进程的第一个命令冻结了整个过程,因此我必须杀死它。 应该注意的是,我试图删除process.communicate行,而用print(command)代替。 这也冻结了过程。我非常基本的当前代码如下:

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()

提供的任何帮助将不胜感激!

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()函数中解析服务器的输出,然后根据收集的输出确定包装的服务器何时需要用户输入,然后才调用talk()函数(当然,从中删除while循环)以获取用户输入。

如果Minecraft服务器试图通过它告诉您一些信息,您还应该同时输出STDERR。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM