将以下内容放入一个文件hello.py(easy_install paramiko
如果你还没有):
hostname,username,password='fill','these','in' import paramiko c = paramiko.SSHClient() c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect(hostname=hostname, username=username, password=password) i,o,e = c.exec_command('ls /') print(o.read()) c.close()
适当填写第一行.
现在输入
python hello.py
你会看到一些ls输出.
现在改为输入
python
然后从解释器类型中
import hello
瞧!它挂了!如果你将代码包装在一个函数中foo
,它将取消它import hello; hello.foo()
.
为什么Paramiko在模块初始化时使用时会挂起? Paramiko如何知道它首先在模块初始化期间被使用?
Paramiko使用单独的线程进行底层传输.你永远不应该有一个产生线程的模块作为导入的副作用.据我所知,有一个可用的导入锁,所以当你的模块中的子线程尝试另一次导入时,它可以无限期地阻塞,因为你的主线程仍然持有锁.(可能还有其他问题,我也不知道)
通常,模块在导入时不应具有任何类型的副作用,否则您将获得不可预测的结果.只是用这个__name__ == '__main__'
技巧推迟执行,你会没事的.
[编辑]我似乎无法创建一个简单的测试用例来重现这个死锁.我仍然认为这是导入的线程问题,因为auth代码正在等待永远不会触发的事件.这可能是paramiko或python中的一个错误,但好消息是,如果你正确地做事,你不应该看到它;)
这是一个很好的例子,为什么你总是想要最小化副作用,以及为什么函数式编程技术变得越来越普遍.