子进程调用的rsync Popen在运行脚本时工作,但在我用py2app生成应用程序时则不行

时间:2015-02-09 10:49:52

标签: python subprocess 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应用程序的独立线程上运行。有谁知道为什么会这样?

2 个答案:

答案 0 :(得分:0)

刚刚通过一个简单的'ls'进行了测试改变Popen调用,但是在运行py2app版本时我仍然无法获得输出。它在运行python脚本时工作得很好。当我杀死py2app版本应用程序时,输出就会被打印出来。

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

答案 1 :(得分: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)