首页 > 解决方案 > 使用 pysftp 成功启动 SFTP 后的 OSError

问题描述

我正在使用putpysftp一些文件上传到 SFTP 服务器。

我有一个 Python 列表filesToUpload_bordet,我正在x使用上下文管理器中的 for 循环上传每个文件,如下所示:

# Enter the sftp server and perform the operations
with pysftp.Connection(host=hostname, 
                        username=username, 
                        password=password) as sftp:
    # Create and cd to the directory where the files will be uploaded
    try:
        sftp.mkdir(f'{lastRun}')
    except OSError:
        append(line=f"{timeStamp} run {lastRun}: {panel} WARNING: sftp directory /ngs/{lastRun} already exists, so not creating\n",logFile=logFile)
    with sftp.cd(f'/ngs/{lastRun}'):
        for x in filesToUpload_bordet:
            # put the vcf files
            sftp.put(x)

我知道上面的截图有效,因为上传成功开始。不过,过了一段时间后,我在 Python 控制台上收到以下错误消息:

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
/nexus/databases/ngsRunStats_FK/postPipeline/scripts/newStrategy/STEPS_postPipeline_prod.py in <module>
----> 1 sftpUpload(panel)

/nexus/databases/ngsRunStats_FK/postPipeline/scripts/newStrategy/STEPS_postPipeline_prod.py in sftpUpload(panel)
     1212                 for x in filesToUpload_bordet:
     1213                     # put the vcf files
---> 1214                     sftp.put(x)
     1215         sftp.close() # this is probably not necessary as I am working on a context manager
     1216         # this message should be sent independently from the coverage check email

~/miniconda3/lib/python3.7/site-packages/pysftp/__init__.py in put(self, localpath, remotepath, callback, confirm, preserve_mtime)
    362 
    363         sftpattrs = self._sftp.put(localpath, remotepath, callback=callback,
--> 364                                    confirm=confirm)
    365         if preserve_mtime:
    366             self._sftp.utime(remotepath, times)

~/miniconda3/lib/python3.7/site-packages/paramiko/sftp_client.py in put(self, localpath, remotepath, callback, confirm)
    757         file_size = os.stat(localpath).st_size
    758         with open(localpath, "rb") as fl:
--> 759             return self.putfo(fl, remotepath, file_size, callback, confirm)
    760 
    761     def getfo(self, remotepath, fl, callback=None):

~/miniconda3/lib/python3.7/site-packages/paramiko/sftp_client.py in putfo(self, fl, remotepath, file_size, callback, confirm)
    715             fr.set_pipelined(True)
    716             size = self._transfer_with_callback(
--> 717                 reader=fl, writer=fr, file_size=file_size, callback=callback
    718             )
    719         if confirm:

~/miniconda3/lib/python3.7/site-packages/paramiko/sftp_client.py in _transfer_with_callback(self, reader, writer, file_size, callback)
    677         while True:
    678             data = reader.read(32768)
--> 679             writer.write(data)
    680             size += len(data)
    681             if len(data) == 0:

~/miniconda3/lib/python3.7/site-packages/paramiko/file.py in write(self, data)
    403             raise IOError("File not open for writing")
    404         if not (self._flags & self.FLAG_BUFFERED):
--> 405             self._write_all(data)
    406             return
    407         self._wbuffer.write(data)

~/miniconda3/lib/python3.7/site-packages/paramiko/file.py in _write_all(self, data)
    520         # a socket).
    521         while len(data) > 0:
--> 522             count = self._write(data)
    523             data = data[count:]
    524             if self._flags & self.FLAG_APPEND:

~/miniconda3/lib/python3.7/site-packages/paramiko/sftp_file.py in _write(self, data)
    206             while len(self._reqs):
    207                 req = self._reqs.popleft()
--> 208                 t, msg = self.sftp._read_response(req)
    209                 if t != CMD_STATUS:
    210                     raise SFTPError("Expected status")

~/miniconda3/lib/python3.7/site-packages/paramiko/sftp_client.py in _read_response(self, waitfor)
    863                 # synchronous
    864                 if t == CMD_STATUS:
--> 865                     self._convert_status(msg)
    866                 return t, msg
    867 

~/miniconda3/lib/python3.7/site-packages/paramiko/sftp_client.py in _convert_status(self, msg)
    896             raise IOError(errno.EACCES, text)
    897         else:
--> 898             raise IOError(text)
    899 
    900     def _adjust_cwd(self, path):

OSError: Failure

这可能不是超时问题吗?我看到我的第一个文件在上午 09:08 成功上传,我在上午 11:49 收到错误消息。

标签: pythonpython-3.xsftppysftp

解决方案


Failure”是 SFTP 错误代码 4 的错误消息,由 OpenSSH SFTP 服务器针对各种问题返回,在 SFTP 协议版本 3 中没有更具体的代码。虽然服务器至少应该返回一个特定的纯文本错误消息,它没有这样做。

上传时您可能会收到一般的“失败”错误消息的常见原因是:

  • 将文件上传到完整文件系统 (HDD)。
  • 超出用户磁盘配额。

有关详细信息,请参阅SFTP 状态/错误代码 4(失败)


推荐阅读