【问题标题】:Python Subprocess.Popen from a threadPython Subprocess.Popen 从一个线程
【发布时间】:2010-11-02 08:46:47
【问题描述】:

我正在尝试使用子进程模块和 Popen 在线程内启动“rsync”。在我调用 rsync 之后,我还需要读取输出。我正在使用通信方法来读取输出。当我不使用线程时,代码运行良好。看来,当我使用线程时,它会挂在通信调用上。我注意到的另一件事是,当我设置 shell=False 时,我在线程中运行时不会从通信中得到任何回报。

【问题讨论】:

    标签: python multithreading subprocess rsync


    【解决方案1】:

    您没有提供任何代码供我们查看,但这里有一个与您描述的类似的示例:

    import threading
    import subprocess
    
    class MyClass(threading.Thread):
        def __init__(self):
            self.stdout = None
            self.stderr = None
            threading.Thread.__init__(self)
    
        def run(self):
            p = subprocess.Popen('rsync -av /etc/passwd /tmp'.split(),
                                 shell=False,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
    
            self.stdout, self.stderr = p.communicate()
    
    myclass = MyClass()
    myclass.start()
    myclass.join()
    print myclass.stdout
    

    【讨论】:

    • 是的,这正是我正在做的事情。不过,我想读取线程内的输出。我还应该注意我使用的是 Python 2.3。我从 2.4 中获取了 subprocess 的副本。
    • 我应该更清楚这就是我正在做的事情,但它不起作用。在这种情况下,通信调用不会返回任何内容,并且命令似乎不会执行。如果我设置 shell=True 通信挂起线程。然后在我停止 python 之后,我最终得到了一个失效的 ssh 进程。
    • 我测试了提供的示例代码,我得到了相同的行为。我尝试用 'ls -la' 之类的不同命令替换,但我没有遇到任何问题,所以我认为它与 rsync 或这个版本的 python 有关。
    • 让它工作。我的环境出了点问题。感谢您的帮助!
    • 只是好奇您为纠正您的问题做了什么?我处于类似的位置,我有一个在线程中运行的子进程,我想在它执行时捕获输出。 'communicate()' 或 'stdout.readlines()' 调用返回任何输出的唯一时间是应用程序完全终止后。如果我从线程中提取相同的代码,它就可以正常工作。
    【解决方案2】:

    这是一个很好的不使用线程的实现: constantly-print-subprocess-output-while-process-is-running

    import subprocess
    
    def execute(command):
        process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        output = ''
    
        # Poll process for new output until finished
        for line in iter(process.stdout.readline, ""):
            print line,
            output += line
    
    
        process.wait()
        exitCode = process.returncode
    
        if (exitCode == 0):
            return output
        else:
            raise Exception(command, exitCode, output)
    
    execute(['ping', 'localhost'])
    

    【讨论】:

    • 需要注意的是,这个实现会阻塞process.stdout.readline()
    • 另请注意,如果进程有一个加载栏,并且在\r 后面重复打印进度,则将universal_newlines=True 添加到Popen 命令很有用。如果没有universal_newlines 选项,您需要等到最后的\n 才能获得一个巨大的字符串(包含连接在一起的所有进度条)。
    猜你喜欢
    • 2013-03-17
    • 2020-10-02
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 2011-05-16
    • 1970-01-01
    相关资源
    最近更新 更多