hyp*_*ser 5 unicode zipfile python-2.7
我正在尝试使用python脚本从中国的服务提供商下载文件(我自己不是从中国)。提供程序给我一个.zip文件,其中包含一个文件名似乎带有汉字的文件。这似乎导致zipfile模块出现故障。
码:
import zipfile
f = "/path/to/zip_file.zip"
if zipfile.is_zipfile(f):
fz = zipfile.ZipFile(f, 'r')
Run Code Online (Sandbox Code Playgroud)
zipfile本身不包含任何非ASCII字符,但其中的文件包含。当我运行上述脚本时,出现以下异常:
Traceback (most recent call last): File "./temp.py", line 9, in <module>
fz = zipfile.ZipFile(f, 'r') File "/usr/lib/python2.7/zipfile.py", line 770, in __init__
self._RealGetContents() File "/usr/lib/python2.7/zipfile.py", line 859, in _RealGetContents
x.filename = x._decodeFilename() File "/usr/lib/python2.7/zipfile.py", line 379, in _decodeFilename
return self.filename.decode('utf-8') File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0xbd in position 30: invalid start byte
Run Code Online (Sandbox Code Playgroud)
我尝试浏览许多类似问题的答案:
如果我输入错了,请纠正我,但它似乎是zipfile模块的未解决问题。
我该如何解决?我应该使用其他替代模块来处理zip文件吗?或其他解决方案?
TIA。
编辑:我可以使用linux命令行实用程序“ unzip”完美地访问/解压缩同一文件。
最近我遇到了同样的问题。这是我的解决方案。我希望它对你有用。
import shutil
import zipfile
f = zipfile.ZipFile('/path/to/zip_file.zip', 'r')
for fileinfo in f.infolist():
filename = fileinfo.filename.encode('cp437').decode('gbk')
outputfile = open(filename, "wb")
shutil.copyfileobj(f.open(fileinfo.filename), outputfile)
outputfile.close()
f.close()
Run Code Online (Sandbox Code Playgroud)
更新:您可以使用以下更简单的解决方案pathlib:
from pathlib import Path
import zipfile
with zipfile.ZipFile('/path/to/zip_file.zip', 'r') as f:
for fn in f.namelist():
extracted_path = Path(f.extract(fn))
extracted_path.rename(fn.encode('cp437').decode('gbk'))
Run Code Online (Sandbox Code Playgroud)
Python 2.x(2.7)和Python 3.x处理模块zipfile中非utf-8文件名的方式有些不同。
首先,它们都检查文件的ZipInfo.flag_bits,如果ZipInfo.flag_bits&0x800,则将使用utf-8解码文件名。
如果以上检查为False,则在Python 2.x中,将返回名称的字节字符串;否则,返回false。在Python 3.x中,模块将使用cp437编码对文件进行解码,并返回解码后的结果。当然,在两个Python版本中,模块都不知道文件名的真实编码。
因此,假设您从ZipInfo对象或zipfile.namelist方法获得了文件名,并且您已经知道该文件名是使用XXX编码编码的。这些是您获取正确的unicode文件名的方法:
# in python 2.x
filename = filename.decode('XXX')
# in python 3.x
filename = filename.encode('cp437').decode('XXX')
Run Code Online (Sandbox Code Playgroud)
ZIP 文件无效。它有一个标志,表明其中的文件名被编码为 UTF-8,但实际上并非如此;它们包含作为 UTF-8 无效的字节序列。也许他们是GBK?也许还有别的事?也许是一些邪恶的不一致的混合物?不幸的是,野外的 ZIP 工具在一致地处理非 ASCII 文件名方面非常非常差。
一个快速的解决方法可能是替换解码文件名的库函数。这是一个猴子补丁,因为没有一种简单的方法可以将您自己的 ZipInfo 类注入 ZipFile,但是:
zipfile.ZipInfo._decodeFilename = lambda self: self.filename
Run Code Online (Sandbox Code Playgroud)
将禁用解码文件名的尝试,并始终返回带有字节字符串filename属性的 ZipInfo,您可以继续以任何适当的方式手动解码/处理。
| 归档时间: |
|
| 查看次数: |
2747 次 |
| 最近记录: |