【问题标题】:Call to POPEN causes hang inside thread调用 POPEN 导致线程内挂起
【发布时间】:2012-10-02 20:37:48
【问题描述】:

我的代码似乎挂在这个 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

代码在SshWorker上的executeScriptOverSSH方法中

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 的调用——我已经在那里使用打印语句进行了检查。有什么想法吗?

【问题讨论】:

    标签: python multithreading popen


    【解决方案1】:

    我已经运行了下面的代码,它运行正常。您提到“如果返回码不为零,则检查输出 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()
    

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

    • 从您称为 runner 的 WorkerThread 中,我不知道 runner 的详细信息,但在进行多线程编程时,最强大的线程安全选项是使用 Queue 进行通信。
    • 有许多优秀的库可以完成您在此处所做的工作。他们经过充分测试并且干净利落。 paramiko 非常棒,Fabric 也非常棒。

    简单的结构远程运行示例

    from fabric.api import run
    
    def anonymous():
        run("uname -a")
    

    【讨论】:

    • 对不起,我没有说得更清楚。如果返回码不为零,除了 check_output barfs 之外,这是可以的。我尝试运行的实际命令是 ssh root@MachineB 'bash -s'
    猜你喜欢
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    • 2020-10-20
    • 2015-04-09
    相关资源
    最近更新 更多