Python 帕拉米科';什么方法对我有效?

Python 帕拉米科';什么方法对我有效?,python,fabric,paramiko,Python,Fabric,Paramiko,我写了一节课: class Remote(object): def __init__(self, address, username, password): self.address = address self.username = username self.password = password def stdout(self, s): print('out: ' + s) def stderr(

我写了一节课:

class Remote(object):
    def __init__(self, address, username, password):
        self.address  = address
        self.username = username
        self.password = password

    def stdout(self, s):
        print('out: ' + s)

    def stderr(self, s):
        print('err: ' + s)

    def sh(self, s):
        from paramiko  import AutoAddPolicy, SSHClient
        from threading import Thread
        from time      import sleep

        ssh = SSHClient()
        ssh.set_missing_host_key_policy(AutoAddPolicy())
        ssh.connect(self.address, username = self.username, password = self.password)
        stdin, stdout, stderr = ssh.exec_command(s)

        def monitor(channel, method):
            while True:
                for line in channel.readlines():
                    method(line)
                sleep(1)

        Thread(target = monitor, args = (stdout, self.stdout)).start()
        Thread(target = monitor, args = (stderr, self.stderr)).start()
然后我试着像这样运行它:

>>> from remote import Remote
>>> address  = <removed>
>>> username = 'root'
>>> password = <removed>
>>> r = Remote(address, username, password)
>>> r.sh('echo Hello')
我只有
方法(channel.read())
方法(channel.readline())
,但在这种情况下,我只看到:

out:
err:
每秒一次-它实际上从未给我以下方面的预期结果:

out: Hello
我知道我的地址、用户名和密码都是正确的,因为我可以将它们输入到
fabric

>>> from fabric.api        import env
>>> from fabirc.operations import sudo
>>> env.host_string, env.user, env.password = address, username, password
>>> sudo('echo Hello')
[<omitted>]: Hello
那么结果应该是:

out: Hello
out: Hello
out: World
out: World
表示两个调用并行运行,而不是:

out: Hello
out: World
out: Hello
out: World

这表明这两个调用是同步运行的。

问题是
监视器中的
循环中的
阻止线程结束。保持第一部分不变,并将最后一行更改为:

def monitor(channel, method):
    while True:
        l = channel.readline()
        if l:
            method(l)
        else:
            break
tout = Thread(target = monitor, args = (stdout, self.stdout))
terr = Thread(target = monitor, args = (stderr, self.stderr))
tout.start()
terr.start()
tout.join()
terr.join()
ssh.close()

将逐行打印给定命令的输出,同时返回一些内容。

我希望这些方法异步运行。它不应该等到命令完成后才返回。如果类的用户关心命令输出的内容,那么他们应该子类化并使用
stdout
stderr
方法。我认为您不明白-这仍然会导致调用是同步的。我在问题中添加了一个编辑来解释。话虽如此,您的代码实际上输出了一些东西,而我的原始代码没有输出任何东西,因此+1表示。此外,我会让您知道,实现同步实际上非常简单。我所要做的就是将
sh
的名称更改为
\u sh
(表示它是私有的),并创建一个新的
sh
,它只启动一个线程并在其上运行
\u sh
,然后返回而不加入。不确定这是否是最优雅的解决方案,但它似乎有效。
out: Hello
out: World
out: Hello
out: World
def monitor(channel, method):
    while True:
        l = channel.readline()
        if l:
            method(l)
        else:
            break
tout = Thread(target = monitor, args = (stdout, self.stdout))
terr = Thread(target = monitor, args = (stderr, self.stderr))
tout.start()
terr.start()
tout.join()
terr.join()
ssh.close()