2015-02-09 2 views
0

Это мой код:Rsync называют подпроцессу Popen работает при запуске скрипта, но не когда я произвожу приложение с py2app

def uploadByRSync(host, user, passwd, src, dst, statusManager): 
    try: 
     os.environ["RSYNC_PASSWORD"] = passwd 
     print host, user, passwd, src, dst 
     parameters = ["rsync", "-azP", "--partial", src ,"{3}@{0}::{2}/{1}".format(host, dst, user, user)] 
     print " ".join(parameters) 
     process = subprocess.Popen(parameters, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) 
     for line in unbuffered(process): 
      if "%" in line: 
       spl = line.split() 
       statusManager.uploadSpeed = spl[2] 
       statusManager.uploaded = spl[1] 
     return not process.wait() 
    except Exception as ex: 
     print ex 
     return False 


newlines = ['\n', '\r\n', '\r'] 
def unbuffered(proc, stream='stdout'): 
    stream = getattr(proc, stream) 
    with contextlib.closing(stream): 
     while True: 
      out = [] 
      last = stream.read(1) 
      # Don't loop forever 
      if last == '' and proc.poll() is not None: 
       break 
      while last not in newlines: 
       # Don't loop forever 
       if last == '' and proc.poll() is not None: 
        break 
       out.append(last) 
       last = stream.read(1) 
      out = ''.join(out) 
      print out 
      yield out 

При работе с версией py2app я никогда не могу получить выход. При работе в качестве скрипта все работает отлично. ps: этот код выполняется в отдельном потоке приложения Qt. Кто-нибудь знает, почему это происходит?

+0

Вы проверили, использует ли py2app ту же версию python, что и при запуске интерпретатора? Проверка 'last == ''' может вести себя по-другому .. – frans

+0

и попробуйте добавить 'bufsize = 0' к вашему вызову' Popen' – frans

ответ

0

Только что сменил вызов Popen простым «ls», но я все еще не могу получить результат при запуске версии py2app. Он отлично работает при запуске скрипта python. Когда я убиваю приложение версии py2app, вывод только что напечатан.

process = subprocess.Popen(["ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) 
+1

Пожалуйста, используйте комментарии или отредактируйте свое сообщение, чтобы добавить дополнительную информацию, а не размещать ответ, который не является ответ. – frans

+0

, пожалуйста, отредактируйте ваш вопрос] (http://stackoverflow.com/posts/28407988/edit) и включите эту информацию туда. Затем удалите этот ответ без ответа. – jfs

0

Скорее всего, у вас есть проблема буферизации потока. Вот как вы можете выводить все строки своего процесса в реальном времени:

import subprocess 
    import select 
    p = subprocess.Popen(parameters, 
         stdout=subprocess.PIPE, stderr=subprocess.PIPE, 
         bufsize=0) 

    poll = [p.stdout.fileno(), p.stderr.fileno()] 

    while True: 
     # check if process is still running and read remaining data 
     if p.poll() is not None: 
      for l in p.stdout.readlines(): 
       print(l) 
      for l in p.stderr.readlines(): 
       print(l) 
      break 

     # blocks until data is being recieved 
     ret = select.select(poll, [], []) 

     for fd in ret[0]: 
      line = p.stdout.readline() if fd == p.stdout.fileno() else p.stderr.readline() 
      print(line) 
+0

Код в вопросе уже читает по одному байту за раз. 'select' не заставит дочерний процесс сбросить свои стандартные потоковые буферы быстрее, то есть, если код OP завершится неудачно; ваш код также может потерпеть неудачу. 'bufsize = 0' по умолчанию на Python 2. Я не знаю, какое влияние на буферизацию оказывает« universal_newlines = True ». OP использует 'stderr = subprocess.STDOUT', поэтому может использоваться [более простой код] (http://stackoverflow.com/a/17698359/4279) – jfs