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

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

但是,为连接设置超时值不起作用,它似乎是创建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)

但是这个超时再次仅用于读/写操作

在paramiko(python)中有一个类似的问题超时,但它只有在创建SSH连接时超时

更新1

在@Martin的评论之后,我实现了一个回调函数,该函数检查sftp获取操作的时间限制:

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

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

 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方法的callback参数:

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

在回调中,如果时间限制到期,请检查传输的持续时间并抛出异常。

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

链接地址: http://www.djcxy.com/p/33641.html

上一篇: Setting timelimit for sftp.get() of Paramiko module

下一篇: How to transfer a file to ssh server in an ssh