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

标签 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=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()

我还尝试设置 channel 的超时值,但它也不起作用

sftp.get_channel.settimeout(10.0)

但是这个超时又只是针对读/写操作

有一个类似的问题Timeout in paramiko (python)但它只对创建 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 源代码,发现其背后的罪魁祸首是 sftp_file.py 的 _close(self,async=False) 方法。 有什么帮助可以解决这个问题吗?


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

 File "/scratch/divjaisw/python2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/scratch/divjaisw/python2.7/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/scratch/divjaisw/python_virtual/lib/python2.7/site-packages/paramiko/sftp_file.py", line 488, in _prefetch_thread
    num = self.sftp._async_request(self, CMD_READ, self.handle, long(offset), int(length))
  File "/scratch/divjaisw/python_virtual/lib/python2.7/site-packages/paramiko/sftp_client.py", line 754, in _async_request
    self._send_packet(t, msg)
  File "/scratch/divjaisw/python_virtual/lib/python2.7/site-packages/paramiko/sftp.py", line 170, in _send_packet
    self._write_all(out)
  File "/scratch/divjaisw/python_virtual/lib/python2.7/site-packages/paramiko/sftp.py", line 133, in _write_all
    n = self.sock.send(out)
  File "/scratch/divjaisw/python_virtual/lib/python2.7/site-packages/paramiko/channel.py", line 715, in send
    return self._send(s, m)
  File "/scratch/divjaisw/python_virtual/lib/python2.7/site-packages/paramiko/channel.py", line 1081, in _send
    raise socket.error('Socket is closed')
error: Socket is closed

最佳答案

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

但是您的服务器不会停止响应。通信处于事件状态。


您所要求的是对操作持续时间的限制。您很难指望这会很容易为您实现。这是一个比较具体的要求。您必须自己实现它。

您可以使用get methodcallback参数:

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

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

有关示例,请参阅 How to timeout Paramiko sftp.put() with signal module or other in Python?

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

关于python - 为 Paramiko 模块的 sftp.get() 设置时间限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40222684/

相关文章:

python - 你的 python 模式钩子(Hook)里有什么?

Python - 除了 (OSError, e) - 不再适用于 3.3.3?

c# - 设置在强类型数据集 TableAdapter 中使用的 CommandTimeout?

sftp - 使用 sftp -b 批处理文件的权限被拒绝

c++ - 将 sftp 协议(protocol)与 libcurl 一起使用——如何列出目录的内容?

python - 带有 json 文件的 python 类型错误 : 'str' object does not support item assignment,

python - 在 python 中从 cURL GET 请求保存 .zip 文件

java - 打开url连接时网站首页重定向如何处理

java - 如何在主线程上围绕 java 中的某些代码设置超时?

python - SFTP 通过 Paramiko : Errno 10061 (probably proxy)