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

标签 python file python-3.8

我正在尝试从多个文件中读取行。有些是 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

__init__之后设置_mode属性。为了避免在使用中添加额外的代码行,您可以子类化 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/

相关文章:

python - 转换多索引数据帧以保留 groupby() 聚合

java - 如何使用文件读取器和字符数组拼凑字符串

c - Vim 从另一个文件中包含的库自动完成

python - 显式关闭文件重要吗?

python - pandas df 中两列之间的累积计数

python - 将 "integer" float 转换为 int 总是会返回最接近的整数吗?

python - Flask - 带有动态标签的切换按钮

aws-lambda - (InvalidRequestException) 调用 GetQueryResults 时......从 Lambda Python 查询 Athena......无法读取结果

python - 在 Python 3.8 上安装 Matplotlib 时出错

python - 为什么不能使用 Python 的 walrus 运算符来设置实例属性?