【问题标题】:A Python Wrapper or Handler for A Minecraft ServerMinecraft 服务器的 Python 包装器或处理程序
【发布时间】:2016-03-30 18:04:50
【问题描述】:

我正在使用 Windows,并且正在为 Minecraft 服务器寻找使用 Python 的处理程序或包装程序,以便我可以自动输入命令而无需用户输入。我在网站上搜索了很多问题,只找到了一半的答案(至少在我的情况下)。我相信我将需要使用 subprocess 模块,但在我尝试 Popen 函数时无法决定使用哪个模块。我找到了针对我的案例修改的答案:

server = Popen("java -jar minecraft_server.jar nogui", stdin=PIPE, stdout=PIPE, stderr=STDOUT)
while True:
    print(server.stdout.readline())
    server.stdout.flush()
    command = input("> ")
    if command:
        server.stdin.write(bytes(command + "\r\n", "ascii"))
        server.stdin.flush()

这确实以某种方式起作用,但每次输入命令时只会打印一行,这是行不通的,我为改变这一点所做的所有努力最终导致程序无法执行任何其他操作,而只是读取。这不是一个重复的问题,因为类似问题中的答案都无法对我有足够的帮助。

【问题讨论】:

    标签: python controller subprocess wrapper minecraft


    【解决方案1】:

    如您所知,您的 server.stdout.readline()input("> ") 正在阻止您的代码执行。
    您需要使您的代码非阻塞,不要等待实际返回您想要的内容,而是检查是否有任何要读取的内容并忽略它,如果没有则继续执行其他操作。

    在 Linux 系统上,您可能可以使用 select module,但在 Windows 上,它只能在套接字上使用。

    我能够通过使用线程和队列使其在 Windows 上运行。 (注意:这是 Python 2 代码)

    import subprocess, sys
    from Queue import Queue, Empty
    from threading import Thread
    
    def process_line(line):
    
        if line == "stop\n": # lines have trailing new line characters
            print "SERVER SHUTDOWN PREVENTED"
            return None
        elif line == "quit\n":
            return "stop\n"
        elif line == "l\n":
            return "list\n"
    
        return line
    
    s = subprocess.Popen("java -jar minecraft_server.jar nogui", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    
    def read_lines(stream, queue):
        while True:
            queue.put(stream.readline())
    
    # terminal reading thread
    q = Queue()
    t = Thread(target=read_lines, args=(sys.stdin, q))
    t.daemon = True
    t.start()
    
    # server reading thread
    qs = Queue()
    ts = Thread(target=read_lines, args=(s.stdout, qs))
    ts.daemon = True
    ts.start()
    
    while s.poll() == None: # loop while the server process is running
    
        # get a user entered line and send it to the server
        try:
            line = q.get_nowait()
        except Empty:
            pass
        else:
            line = process_line(line) # do something with the user entered line
            if line != None:
                s.stdin.write(line)
                s.stdin.flush()
    
        # just pass-through data from the server to the terminal output
        try:
            line = qs.get_nowait()
        except Empty:
            pass
        else:
            sys.stdout.write(line)
            sys.stdout.flush()
    

    【讨论】:

    • 非常感谢您,因为我失去了找到任何类似的实际工作的希望。我真的很抱歉我这么晚才注意到,因为我知道不会有即时回复。谢谢你:)
    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 2011-06-18
    相关资源
    最近更新 更多