使用unittest.TextTestRunner执行含Paramiko SSH连接的PyUnit测试时挂起
解决unittest.TextTestRunner运行带Paramiko SSH连接测试时挂起的问题
我之前碰到过一模一样的情况,排查下来主要是unittest的输出流和Paramiko的IO操作冲突,或者是SSH连接缺少超时/交互处理导致的阻塞。给你几个实用的解决方向:
1. 给SSH连接添加超时参数
Paramiko的client.connect()默认没有超时限制,一旦网络不通或者服务器无响应,就会无限挂起。先加上超时参数,强制连接超时,这样至少能确定是连接问题还是其他冲突:
client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) print("Before connect") # 加上10秒超时,可根据实际情况调整时长 client.connect(hostname=host, timeout=10) print("Connected to %s" % host)
2. 启用unittest的buffer模式
TextTestRunner默认会实时输出测试日志,而Paramiko底层的IO操作可能和这个输出流产生死锁。开启buffer=True可以捕获测试过程中的stdout/stderr,避免IO冲突,这是最快速的验证方法:
suite = unittest.TestLoader().loadTestsFromTestCase(Test) # 加入buffer=True参数 testResult = unittest.TextTestRunner(verbosity=2, buffer=True).run(suite)
3. 自定义TestRunner隔离输出流
如果buffer模式没用,可以自定义一个TestRunner,把unittest的输出流和系统默认的stdout隔离开,避免和Paramiko的IO操作互相干扰:
import sys import unittest from io import StringIO class CustomTextTestRunner(unittest.TextTestRunner): def __init__(self, stream=None, **kwargs): if stream is None: stream = StringIO() super().__init__(stream, **kwargs) self.original_stdout = sys.stdout sys.stdout = self.stream def run(self, test): try: result = super().run(test) # 测试结束后统一输出捕获的内容 print(self.stream.getvalue()) return result finally: # 恢复原来的stdout sys.stdout = self.original_stdout # 使用自定义Runner运行测试 suite = unittest.TestLoader().loadTestsFromTestCase(Test) testResult = CustomTextTestRunner(verbosity=2).run(suite)
4. 排查SSH连接的交互需求
有些服务器会需要额外的交互验证(比如密码输入、二次验证),虽然你用了AutoAddPolicy()跳过主机密钥确认,但可能还有其他问题。可以显式指定登录参数,禁用密钥查找和代理,强制用密码登录(如果适用的话):
client.connect( hostname=host, username="your_username", password="your_password", look_for_keys=False, # 禁用本地密钥查找 allow_agent=False, # 禁用SSH代理 timeout=10 )
建议先从第1和第2种方法开始试,这两个操作最简单,大概率能解决问题。如果还是不行,再检查SSH连接的交互配置或者用自定义Runner隔离输出流。
内容的提问来源于stack exchange,提问作者ivan_ochc
相关产品推荐
相关产品推荐

