如何解决fileinput.hook_compressed有时给我字符串,其他时候给我字节
我正在尝试从许多文件中读取行。有些压缩,而另一些则是纯文本文件。在Python 2.7中,我一直在使用以下代码,并且可以正常工作:
for line in fileinput.input(filenames,openhook=fileinput.hook_compressed):
match = REGEX.match(line)
if (match):
# do things with line...
现在,我移至Python 3.8,它仍然可以与纯文本文件一起正常工作,但是当遇到gzip压缩文件时,出现以下错误:
TypeError: cannot use a string pattern on a bytes-like object
解决此问题的最佳方法是什么?我知道我可以检查line
是否是字节对象并将其解码为字符串,但是我宁愿使用一些标志来自动将行始终迭代为字符串(如果可能);而且,我更愿意编写适用于Python 2和3的代码。
解决方法
fileinput.input
根据是否获取压缩文件而执行根本不同的操作。对于文本文件,它以常规open
打开,默认情况下,该模式实际上以文本模式打开。对于gzip.open
,默认模式是二进制,这对于未知内容的压缩文件是明智的。
仅二进制限制由fileinput.FileInput
人为施加。从__init__
方法的代码中:
# restrict mode argument to reading modes if mode not in ('r','rU','U','rb'): raise ValueError("FileInput opening mode must be one of " "'r','U' and 'rb'") if 'U' in mode: import warnings warnings.warn("'U' mode is deprecated",DeprecationWarning,2) self._mode = mode
这为您提供了两种解决方法。
选项1
在_mode
之后设置__init__
属性。为了避免在您的用法中添加额外的代码行,您可以将fileinput.FileInput
子类化并直接使用该类:
class TextFileInput(fileinput.FileInput):
def __init__(*args,**kwargs):
if 'mode' in kwargs and 't' in kwargs['mode']:
mode = kwargs.pop['mode']
else:
mode = ''
super().__init__(*args,**kwargs)
if mode:
self._mode = mode
for line in TextFileInput(filenames,openhook=fileinput.hook_compressed,mode='rt'):
...
选项2
使用未记录的前导下划线进行处理非常麻烦,因此,您可以为zip文件创建自定义钩子。这实际上很容易,因为您可以将fileinput.hook_compressed
的代码用作模板:
def my_hook_compressed(filename,mode):
if 'b' not in mode:
mode += 't'
ext = os.path.splitext(filename)[1]
if ext == '.gz':
import gzip
return gzip.open(filename,mode)
elif ext == '.bz2':
import bz2
return bz2.open(filename,mode)
else:
return open(filename,mode)
选项3
最后,您始终可以将字节解码为unicode字符串。显然,这不是可取的选择。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。