Python 为Paramiko模块的sftp.get()设置时间限制

Python 为Paramiko模块的sftp.get()设置时间限制,python,timeout,sftp,paramiko,Python,Timeout,Sftp,Paramiko,我正在使用Paramiko的SFTP客户端将文件从远程服务器下载到客户端(即获取操作) 要传输的文件有点大~1GB。 因此,如果时间超过10秒,我希望get操作超时 但是设置connect的超时值不起作用,它似乎只是创建SSH连接的超时,而不是整个SSH连接的超时 ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(host, username=usern

我正在使用Paramiko的SFTP客户端将文件从远程服务器下载到客户端(即获取操作)
要传输的文件有点大~1GB。
因此,如果时间超过10秒,我希望get操作超时

但是设置connect的超时值不起作用,它似乎只是创建SSH连接的超时,而不是整个SSH连接的超时

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=username, password=password, timeout=10.0)
sftp = ssh.open_sftp()
start_time = time.time()
sftp.get(local_path,remote_path)
elapsed_time = time.time()-start_time
print elapsed_time
sftp.close()
我还尝试设置通道的超时值,但它也不起作用

sftp.get_channel.settimeout(10.0)
但此超时同样仅用于读/写操作

有一个类似的问题,但它只有创建SSH连接时超时的答案


更新1:根据@Martin的注释,我实现了一个回调函数,用于检查sftp的get操作的时间限制:

import paramiko
import time

Class TimeLimitExceeded(Exception):
    pass

timelimit = 10
start_time = time.time()

def _timer():
    elapsed_time = time.time()-start_time
    if elapsed_time > timelimit:
        raise TimeLimitExceeded

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=username, password=password, timeout=10.0)
sftp = ssh.open_sftp()
try:
    sftp.get(local_path,remote_path,_timer)
except TimeLimitExceeded:
    print "The operation took too much time to complete"
sftp.close()
但是,除了异常之外,需要花费很多时间,代码在某个地方被阻塞了。 我深入到Paramiko源代码中,发现它背后的罪魁祸首是
\u close(self,async=False)
方法的
sftp\u file.py
有什么可以帮忙的吗


更新2:如果超过时间限制,尝试关闭频道本身。 然后,异常被刷新到控制台,因为
预取
是由单独的守护进程线程实现的

文件“/scratch/divjaisw/python2.7/lib/python2.7/threading.py”,第801行,在引导程序内部
self.run()
文件“/scratch/divjaisw/python2.7/lib/python2.7/threading.py”,第754行,运行中
自我目标(*自我参数,**自我参数)
文件“/scratch/divjaisw/python_virtual/lib/python2.7/site packages/paramiko/sftp_File.py”,第488行,在预取线程中
num=self.sftp.\u异步\u请求(self、CMD\u READ、self.handle、long(偏移量)、int(长度))
文件“/scratch/divjaisw/python_virtual/lib/python2.7/site packages/paramiko/sftp_client.py”,第754行,在异步请求中
自发送数据包(t,msg)
文件“/scratch/divjaisw/python_virtual/lib/python2.7/site packages/paramiko/sftp.py”,第170行,在发送包中
自述(全部写出)
文件“/scratch/divjaisw/python_virtual/lib/python2.7/site packages/paramiko/sftp.py”,第133行,全部写入
n=自存储发送(发出)
文件“/scratch/divjaisw/python_virtual/lib/python2.7/site packages/paramiko/channel.py”,第715行,在send中
返回自我。\u发送(s,m)
文件“/scratch/divjaisw/python_virtual/lib/python2.7/site packages/paramiko/channel.py”,第1081行,在_send中
升起套接字。错误('套接字已关闭')
错误:套接字已关闭

你要求的不是真正的超时。术语“超时”用于限制等待响应的时间

但您的服务器不会停止响应。通信处于活动状态


你所要求的,是对手术持续时间的限制。你很难期望它能很快为你实现。这是一个相当具体的要求。你必须自己实现它

您可以使用的
callback
参数:

在回调中,检查传输的持续时间,如果时间限制过期,则抛出异常

这不会立即取消传输。为了优化传输性能,Paramiko将最多100个读取请求排队发送到服务器(请参阅)。一旦您尝试取消传输,Paramiko必须等待(最多100个)对这些请求的响应以清除队列

def get(self, remotepath, localpath, callback=None):