我正在尝试创建一个脚本,该脚本将下载一个ZIP文件并将其解压缩。
我正在Windows Server 2016上使用Python 2.7。
我创建了一个如下所示的下载脚本:
ftp = FTP()
ftp.connect("***")
ftp.login("***","***")
ftp.cwd(ftppath)
ftp.retrbinary("RETR " + filename ,open(tempfile, 'wb').write)
ftp.quit()
还有一个zip提取脚本:
zip_ref = zipfile.ZipFile(tempfile, 'r')
zip_ref.extractall(localpath)
zip_ref.close()
这些工作是独立进行的。含义:如果我在测试的ZIP文件上运行提取脚本,它将提取文件。另外,如果我从服务器运行FTP脚本,它将下载文件。
但是!如果我一起运行这些脚本,这意味着我从FTP服务器下载了文件然后解压缩,它将返回错误:“文件不是Zip文件”。
谁知道为什么会这样? 我检查了以下内容:
编辑
我一直在阅读有关IO字节之类的内容,但是在实现它方面没有任何运气。
答案 0 :(得分:1)
可能是因为这种糟糕的一线做法:
ftp.retrbinary("RETR " + filename ,open(tempfile, 'wb').write)
open(tempfile, 'wb').write
对于关闭文件的时间不提供任何保证。您不会在任何地方存储open
返回的句柄,因此无法决定何时close
文件(并确保完整的磁盘写入)。
因此,当尝试以读取模式打开文件时,文件的最后一部分可能还没有被写入磁盘。并且链接下载+解压缩会触发该错误(当2次单独执行留出了刷新和关闭文件的时间)
最好使用这样的上下文管理器:
with open(tempfile, 'wb') as f:
ftp.retrbinary("RETR " + filename ,f.write)
因此,退出with
块时,文件将被刷新并关闭(当然,在此块 之外执行文件读取操作)。