我正在编写一段代码,打开一个(可能是gzip)文本文件,可以在Python 2和Python 3中运行。
如果我只有普通的文本文件(未压缩),我可以这样做:
import io
for line in io.open(file_name, encoding='some_encoding'):
pass
如果我不关心解码(在python 2/3中使用字符串/字节)
if file_name.endswith('.gz'):
file_obj = gzip.open(file_name)
else:
file_obj = open(file_name)
for line in file_obj:
pass
我怎样才能顺利地处理这两种情况呢?换句话说,如何将解码与gzip.open()平滑地集成?
答案 0 :(得分:1)
我对此进行了简单测试,似乎做得对。您可以向gzip.GzipFile
和io.open
提供文件obj,以便
import io
import gzip
f_obj = open('file.gz','r')
io_obj = io.open(f_obj.fileno(), encoding='UTF-8')
gzip_obj = gzip.GzipFile(fileobj=io_obj, mode='r')
gzip_obj.read()
这给了我一个UnicodeDecodeError
,因为我正在阅读的文件实际上并不是UTF-8所以看起来它做的是正确的。
出于某种原因,如果我使用io.open
直接打开file.gz
gzip
表示该文件不是压缩文件。
<强>更新强> 是的,这很愚蠢,开始时流是错误的方式。
测试文件
ö
ä
u
y
以下代码使用定义的编解码器
解码压缩文件import codecs
import gzip
gz_fh = gzip.open('file.gz')
ascii = codecs.getreader('ASCII')
utf8 = codecs.getreader('UTF-8')
ascii_fh = ascii(gz_fh)
utf8_fh = utf8(gz_fh)
ascii_fh.readlines()
-> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
utf8_fh.readlines()
-> [u'\xf6\n', u'\xe4\n', u'u\n', u'y']
codecs.StreamReader
接受一个流,因此您应该能够将压缩或未压缩的文件传递给它。