调用POPEN会导致挂起内部线程

时间:2012-10-02 20:37:49

标签: python multithreading popen

我的代码似乎挂在这个popen调用上

command = "ls"
commandList = shlex.split(command)
print("Executing " + command +"\n")
print(commandList)
output = "#" * 10 + "\n" + server.name + "\n\n"
process = subprocess.Popen(
    command,
    shell=True,
    stdin=subprocess.PIPE, 
    stdout=subprocess.PIPE)
output = process.communicate()[0]
#scriptRunner.threadComplete(output)
return output

代码位于executeScriptOverSSH

上的SshWorker方法中
class WorkerThread(threading.Thread):
    def __init__(self, pathToScript, server, runner):
        super(WorkerThread, self).__init__()
        self.scriptRunner = runner
        self.server = server
        self.pathToScript = pathToScript
        self.sshWorker = SshWorker.SshWorker()

    def run(self):
        print('Thread Starting')
        output = self.sshWorker.executeScriptOverSSH(
            self.server, 
            self.pathToScript)
        print('Thread Finishing!')
        self.scriptRunner.threadComplete(output)`

线程永远不会超过对Popen的调用 - 我已经通过使用print语句进行了检查。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我运行以下代码并且运行正常。您提到“check_output barfs,如果返回代码非零”,请查看check_output docs它引发一个CalledProcessError异常,您可以捕获并包含一个漂亮结构中的所有错误详细信息。

import threading, subprocess, random, time, pprint
from subprocess import check_output

class WorkerThread(threading.Thread):
    def __init__(self, user, host, script, runner):
        super(WorkerThread, self).__init__()
        self.user = user
        self.host = host
        self.script = script
        self.runner = runner

    def run(self):
        cmd = "ssh {user}@{host} 'bash -s' < {script}".format(**self.__dict__)
        self.runner.complete(check_output(cmd, shell=True))

class Runner(object):
    def complete(self, output):
        print 'output:\n', output

WorkerThread('marwan', 'homebox', 'local_script.sh', Runner()).start()

上面的代码遵循您在问题中发布的相同结构。但我不建议你采取这种方法,这里有一些建议:

  • 你从WorkerThread调用runner,我不知道runner的详细信息,但在进行多线程编程时,最强大的线程安全选项是使用Queue进行通信。
  • 有许多优秀的图书馆可以做你在这里做的事情。它们经过了充分的测试并且干净利落。 paramiko非常好,Fabric也很棒。

简单的结构远程运行示例

from fabric.api import run

def anonymous():
    run("uname -a")