【问题标题】:TypeError: can only concatenate tuple (not "str") to tupleTypeError:只能将元组(不是“str”)连接到元组
【发布时间】:2013-08-12 15:03:34
【问题描述】:

我有一个巨大的文本文件(1 GB),其中每个“行”都符合语法:

[number] [number]_[number]

例如:

123 123_1234
45 456_45    12 12_12

我收到以下错误:

  line 46, in open_delimited
    pieces = re.findall(r"(\d+)\s+(\d+_\d+)", remainder + chunk, re.IGNORECASE)
TypeError: can only concatenate tuple (not "str") to tuple

关于此代码:

def open_delimited(filename, args):
    with open(filename, args, encoding="UTF-16") as infile:
        chunksize = 10000
        remainder = ''
        for chunk in iter(lambda: infile.read(chunksize), ''):
            pieces = re.findall(r"(\d+)\s+(\d+_\d+)", remainder + chunk, re.IGNORECASE)
            for piece in pieces[:-1]:
                yield piece
            remainder = pieces[-1]
        if remainder:
            yield remainder

filename = 'data/AllData_2000001_3000000.txt'
for chunk in open_delimited(filename, 'r'): 
    print(chunk)   

【问题讨论】:

  • Remainder 是循环中第二次迭代中的元组而不是字符串
  • 如果chunk 是部分记录,您的代码也会失败。在这种情况下,您没有匹配项。最好将它添加到remainder,拆分然后尝试在适当的地方拆分它。

标签: python tuples


【解决方案1】:
当模式中给出多个捕获组时,

re.findall() 返回一个元组序列。您的模式有两个这样的组。因此,每个piece(number, number_number) 对组成:

>>> re.findall(r"(\d+)\s+(\d+_\d+)", '45 456_45    12 12_12')
[('45', '456_45'), ('12', '12_12')]

请注意,由于您只匹配空格和数字re.IGNORECASE 标志完全是多余的。

您将最后一个这样的piece 分配给remainder,然后循环备份并将其添加到chunk,这不起作用:

>>> ('12', '12_12') + '123 123_1234\n'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate tuple (not "str") to tuple

也许您想再次将这些值重新加入一段有效的文本中:

remainder = '{} {} '.format(*pieces[-1])

【讨论】:

    【解决方案2】:

    如前所述,您的处理中有一个错误:findall() 给出了一个元组列表。

    一种替代方法可能是

    def open_delimited(filename, args):
        with open(filename, args, encoding="UTF-16") as infile:
            chunksize = 10000
            remainder = ''
            for chunk in iter(lambda: infile.read(chunksize), ''):
                remainder += chunk # add it to the to-be-processed string
                pieces = list(re.finditer(r"(\d+)\s+(\d+_\d+)", remainder, re.IGNORECASE))
                # Those pieces are match objects.
                for piece in pieces[:-1]: # omit the last one, as before
                    yield piece.group() # the whole match
                remainder = remainder[pieces[-1].start()] # the last one tells us where to start again.
            if remainder:
                yield remainder
    

    这里,pieces 不是字符串元组,而是匹配对象。它们不仅告诉我们它们包含什么,还告诉我们它们来自哪里。

    这允许轻松“重新创建”“剩余部分”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-13
      • 2022-01-11
      • 1970-01-01
      • 2020-04-11
      • 1970-01-01
      • 2021-07-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多