gpt4 book ai didi

python - fileinput.hook_compressed 有时给我字符串,有时给我字节

转载 作者:行者123 更新时间:2023-12-04 08:51:01 25 4
gpt4 key购买 nike

我正在尝试从多个文件中读取行。有些是 gzip 压缩的,有些是纯文本文件。在 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,它仍然可以处理纯文本文件,但是当它遇到 gzipped 文件时,我收到以下错误:
TypeError: cannot use a string pattern on a bytes-like object
解决这个问题的最佳方法是什么?我知道我可以检查是否 line是一个字节对象并将其解码为字符串,但如果可能,我宁愿使用一些标志来自动将行作为字符串进行迭代;而且,我更愿意编写同时适用于 Python 2 和 3 的代码。

最佳答案

fileinput.input 根据它是否获得 gzip 文件,做根本不同的事情。对于文本文件,它以常规 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', 'rU', '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 文件创建自定义 Hook 。这实际上很简单,因为您可以使用 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
最后,您始终可以将字节解码为 un​​icode 字符串。这显然不是更好的选择。

关于python - fileinput.hook_compressed 有时给我字符串,有时给我字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64105756/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com