Я использую SFTP-клиент Paramiko для загрузки файла с удаленного сервера клиенту (т. Е. Операция получения)
Файл, который нужно передать, немного огромен ~ 1 ГБ.
Так что я хотел бы получить операцию до таймаута, если время больше 10 секунд.Установка timelimit для sftp.get() модуля Paramiko
Но установка значения таймаута для подключения не работает. Похоже, что это таймаут для создания 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)
Но этот таймаут снова только для операций чтения/записи
Существует аналогичный вопрос Timeout in paramiko (python), но у него есть только ответ на таймаут при создании SSH-соединения
Обновление 1
После замечаний @Martin я реализовал функцию обратного вызова, которая проверяет временной предел для операции GET из 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()
Но время, за исключением исключения много, код блокировки где-то. Я погрузился в исходный код Парамико и нашел виновника позади этого метода _close(self,async=False)
sftp_file.py
Любая помощь, чтобы обойти это?
Update 2
Попытка закрыть канал сам, если TimeLimit превышен. Тогда исключение продувают утешать как 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
Он блокируется бесконечно? Или временно?Где именно в '_close' он блокируется? На вызов '_finish_responses'? –
Он временно блокирует. Фактически он вообще не блокирует, но попадает в цикл while внутри '_read_response (self, waitfor = None)', здесь waitfor = 6781, который вызывается '_request' и который сам вызывается by '_close' с' async = False' –
Я добавил возможное объяснение в свой ответ. Хотя полный столбец поможет лучше проанализировать проблему. –