2014-11-30 3 views
0

Я пытаюсь запустить сервер minecraft через Python 2.7, и он работает нормально. Но когда я пытаюсь передать команду stop, она ничего не делает, пока сервер ничего не выведет.stdout readline() blocking

Это мой код:

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», но я хочу, чтобы это работало на всех платформах, так что это не вариант для меня.

Как это сделать, чтобы я мог запускать любую команду в любое время?

Update:

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

+0

В чем проблема? – Elisha

+0

Как я уже говорил выше. «Но когда я пытаюсь передать команду stop, она ничего не делает, пока сервер ничего не выведет». @Elisha – Mike

ответ

1

Есть несколько проблем здесь:

  1. Вы смешиваете звонки в .communicate() и .stdout.readline(), которые оба пытаются читать из stdout.
  2. Вы пытаетесь прочитать из стандартного вывода subprocess на двух отдельных потоках одновременно.

Хотя ни одна из этих вещей строго незаконна, как сильно нецелесообразной и привести к проблемам, как этот.

Я бы порекомендовал иметь один монитор резьбы stdout/stderr (с .communicate(input=None)), а другой вручную разговаривал с stdin (с .stdin.write() или аналогичным).

+0

Будет ли это исправлять мою проблему, а также как я могу это достичь? – Mike

+0

@ user2900873: Измените метод 'run()' для использования '.communicate()' и измените метод 'stop()' для использования '.stdin.write()'. – Kevin

+0

Не могу заставить его работать, я не получаю никакого вывода от фактического сервера. Я обновляю сообщение своим текущим кодом. – Mike