Python中re.findall的明显限制

时间:2018-03-06 14:54:22

标签: python regex data-analysis

我有一个包含数据(定义一些数学对象)的文件,格式很不方便,我想用Python 3将它转换为JSON。因为文件很大(它包含921,497个对象,每个对象需要多行定义),我使用模块mmap加载我使用re.findall分析的内容。我的问题是我只获得了前99999个条目,我想知道这个限制来自哪里?我没有收到任何错误,我找不到解释。

我做了一些小测试来找到限制,但我获得的数字比99999大得多:

>>> import re
>>> len(re.search(r"a{1,9999999}", "a"*(2*10**6)).group())
2000000
>>> len(re.findall(r"a", "a"*(2*10**6)))
2000000
>>> import sre_constants
>>> sre_constants.MAXGROUPS
2147483647

有没有人知道如何超越这个限制,或者更好的方法来收集数据?

我的代码(最多保存文件)如下:

"""
Transform dataset for CICY 4-fold to JSON

arxiv: 1303.1832
http://www-thphys.physics.ox.ac.uk/projects/CalabiYau/Cicy4folds/index.html
"""

import os, mmap, json, tarfile, tempfile
import regex as re

CICY4_REGEX = b"""\
MATRIX NUMBER :\s+(\d+)
SIZE :\s+(\d+)\s+(\d+)
EULERNUMBER :\s+(\d+)
([\d\s\|]+)
"""
cicy4_pattern = re.compile(CICY4_REGEX, re.MULTILINE)

json_data = {}
last_ind = 0

with open('cicy4folds.txt', 'r') as f,\
        mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m:

    for data in cicy4_pattern.findall(m):

        dic = {"vec": [], "matrix": []}

        ind = int(data[0])
        if ind != last_ind + 1:
            print(ind)
        last_ind = ind

        #dic["id"] = int(data[0])
        dic["size"] = (int(data[1]), int(data[2]))
        dic["euler"] = int(data[3])

        for line in data[4].decode("utf-8").split("\n")[:-1]:
            ind, row = line.split(" | ")
            dic["vec"].append(int(ind))
            dic["matrix"].append(list(map(int, row.split())))

        json_data[int(data[0])] = dic

print("Size: ", len(json_data))

可以找到文件cicy4folds.txt here。以下是两个数据示例:

MATRIX NUMBER : 26538
SIZE :   6 10
EULERNUMBER :  480
1 | 0 0 0 0 0 0 0 0 1 1
1 | 0 0 0 0 0 0 1 1 0 0
1 | 0 0 0 0 1 1 0 0 0 0
1 | 0 0 1 1 0 0 0 0 0 0
1 | 1 1 0 0 0 0 0 0 0 0
9 | 1 1 1 1 1 1 1 1 1 1

MATRIX NUMBER : 26539
SIZE :   6  4
EULERNUMBER :  720
1 | 0 0 0 2
1 | 0 0 0 2
1 | 0 0 1 1
1 | 0 0 1 1
2 | 1 1 0 1
2 | 1 1 1 0

1 个答案:

答案 0 :(得分:1)

你的正则表达方式:)

您可以将其更改为:

 CICY4_REGEX = b"""\
 MATRIX NUMBER :\s*(\d+)
 SIZE :\s+(\d+)\s+(\d+)
 EULERNUMBER :\s+(\d+)
 ([\d\s\|]+)
 """