stdout readline()阻塞

时间:2014-11-30 15:47:06

标签: python python-2.7

我正在尝试通过Python 2.7运行一个Minecraft服务器,它运行正常。 但是当我尝试将stop命令传递给它时,它在服务器输出内容之前不会执行任何操作。

这是我的代码:

import os, sys, subprocess, threading, time

class Server:

    def start(self):
        t = threading.Thread(target=self.run)
        t.daemon = True
        t.start()

    def run(self):
        self.p = subprocess.Popen('java -Xmx512M -Xms512M -jar minecraft_server.1.8.1.jar nogui', 
            cwd=os.path.join(os.getcwd(), 'server'), 
            stdin=subprocess.PIPE, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE, 
            shell=True)

        while True:
            nextline = self.p.stdout.readline()
            print self.p.poll()
            if nextline == '' and self.p.poll() != None:
                break

            if not nextline == '':
                sys.stdout.write(nextline)

            sys.stdout.flush()

    def stop(self):
        self.p.communicate(input='stop')[0]
#endclass

s = Server()
s.start()

count = 0

# keep running
while True:
    count += 1

    if count == 15:
        s.stop()
        print "STOPPING SERVER"

    time.sleep(1)

输出图片:http://i.imgur.com/KgB3T9S.png 我想让它不要停在那里。

15秒后停止测试是否可以让它正常工作,但我不知道如何解决这个问题。我看到一些使用'fcntl'的解决方案,但我希望这可以在所有平台上运行,因此对我来说不是一个选项。

我怎样才能这样做,以便我可以随时运行任何命令?

更新

import os, sys, subprocess, threading, time

class Server:

    def start(self):
        t = threading.Thread(target=self.run)
        t.daemon = True
        t.start()

    def run(self):
        self.p = subprocess.Popen('java -Xmx512M -Xms512M -jar minecraft_server.1.8.1.jar nogui', 
            cwd=os.path.join(os.getcwd(), 'server'), 
            stdin=subprocess.PIPE, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE, 
            shell=True)

        print "started server"

        while True:
            outs, errs = self.p.communicate(input=None)
            print outs.decode()
        print "TEST"

    def stop(self):
        self.p.stdin.write('stop')
#endclass

s = Server()
s.start()

count = 0

# keep running
while True:
    count += 1

    print count

    if count == 15:
        s.stop()
        print "STOPPING SERVER"

    time.sleep(1)

输出图片:http://i.imgur.com/U6RcE3K.png

1 个答案:

答案 0 :(得分:1)

这里有很多问题:

  1. 您正在混合对.communicate().stdout.readline()的调用,这些调用都试图从stdout读取。
  2. 您正试图同时在两个单独的线程上读取子进程的标准输出。
  3. 虽然这些都不是严格非法,但两者都是非常不可取的,并导致像这样的问题。

    我建议让一个线程监视器stdout / stderr(带.communicate(input=None)),另一个手动说话stdin(带.stdin.write()或类似)。