“ IOError:大小不匹配!”通过SFTP检索文件时

时间:2018-12-27 13:05:46

标签: python paramiko pysftp

我有一个脚本,该脚本可用于定期通过SFTP检索特定文件。有时,脚本会因以下输出而出错:

Traceback (most recent call last):
  File "ETL.py", line 304, in <module>
    get_all_files(startdate, enddate, "vma" + 
foldernumber + "/logs/", txtype[1] + single_date2 + ".log", txtype[2] + 
foldernumber + "\\", sftp)
  File "ETL.py", line 283, in get_all_files
    sftp.get(sftp_dir + filename, local_dir + filename)
  File "C:\Python27\lib\site-packages\pysftp\__init__.py", line 249, in get
    self._sftp.get(remotepath, localpath, callback=callback)
  File "C:\Python27\lib\site-packages\paramiko\sftp_client.py", line 806, in get
    "size mismatch in get!  {} != {}".format(s.st_size, size)
IOError: size mismatch in get!  950272 != 1018742

我已经浏览了Paramiko文档,但没有看到有关触发此错误的解释。此外,该代码通常可以在以后的尝试中成功运行,或者将成功地针对日期范围内的前几个文件运行,然后在下载我需要检索的所有文件的过程中出错。这样的其他答案说,这可能与驱动器上的可用空间有关,但是我尝试清除目标文件夹,但并没有帮助。我试图下载到网络驱动器/云存储,如果有任何区别。

这是我用来检索文件(通过Paramiko)的函数和代码:

def get_all_files(start_date, end_date, sftp_dir, filename, local_dir,  \
                sftp_connection):

    sftp.get(sftp_dir + filename, local_dir + filename)

with pysftp.Connection('******.com', username='*****', password='******',  cnopts=cnopts) as sftp:
    get_all_files(startdate, enddate, "vma" + foldernumber + "/logs/", txtype[1] + single_date2 + ".log", txtype[2] + foldernumber + "\\", sftp)

我希望在不产生此错误的情况下检索所有可下载文件。

1 个答案:

答案 0 :(得分:2)

如果本地目录上复制文件的大小与远程文件的预取大小不匹配,则Paramiko-library的get函数将引发错误消息IOError: size mismatch in get! 950272 != 1018742

with open(localpath, "wb") as fl:
    size = self.getfo(remotepath, fl, callback)
s = os.stat(localpath)
if s.st_size != size:
    raise IOError(
        "size mismatch in get!  {} != {}".format(s.st_size, size)
    )

如果连接和传输过程没有问题,为什么会发生这种情况?

在检查Paramiko代码并尝试调试此问题时,我的本地文件系统的异常行为引起了我的注意。对于从远程文件系统复制的每个文件,本地文件系统都需要花费一些时间来处理文件,以注册正确的文件大小。

此行为使我想起了一个假设,即Paramiko库的get函数确实正确处理了文件,但它并不等待本地文件系统进行适应,因此可能会获得状态(包括大小)。在使用s = os.stat(localpath)使用getfo函数处理完文件后,立即返回本地文件。

这可能导致本地文件大小和正确预取的远程文件大小之间不一致,因此可能引发IOError "size mismatch in get! {} != {}".format(s.st_size, size)

这也将解释为什么错误不能始终如一地重现,因为Python解释器始终在与本地操作系统的同步有关的不同环境下工作。

我如何为我解决这个问题?

我操纵了get函数的Paramiko代码,该代码可以在“ sftp_client.py”的第785行找到,并在文件处理中添加了localsize = fl.tell(),从而相应地进行了大小检查:

with open(localpath, "wb") as fl:
    size = self.getfo(remotepath, fl, callback)
    localsize = fl.tell()
if localsize != size:
    raise IOError(
        "size mismatch  {} != {}".format(localsize, size)
    )

这应该避免以某种方式存在缺陷的本地文件大小检查s = os.stat(localpath)替换为可以正常工作的检查,该检查在文件处理期间使用文件对象来获取本地文件的大小。