Кэширование скомпилированных объектов регулярных выражений в Python?

Каждый раз, когда импортируется файл python, содержащий большое количество статических регулярных выражений, циклы ЦП тратятся на компиляцию строк в соответствующие конечные автоматы в памяти.

a = re.compile("a.*b")
b = re.compile("c.*d")
...

Вопрос: Можно ли хранить эти регулярные выражения в кэше на диске в предварительно скомпилированном виде, чтобы не выполнять компиляцию регулярных выражений при каждом импорте?

Пикировка объекта просто делает следующее, вызывая компиляцию в любом случае:

>>> import pickle
>>> import re
>>> x = re.compile(".*")
>>> pickle.dumps(x)
"cre\n_compile\np0\n(S'.*'\np1\nI0\ntp2\nRp3\n."

И re объекты не подлежат маршаллингу:

>>> import marshal
>>> import re
>>> x = re.compile(".*")
>>> marshal.dumps(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: unmarshallable object

person Sufian    schedule 15.09.2008    source источник
comment
К сожалению, у моего приложения (900 регулярных выражений и их количество) тоже есть эта проблема. К сожалению, я не вижу решения в этой теме.   -  person Tal Weiss    schedule 01.07.2010


Ответы (7)


Можно ли хранить эти регулярные выражения в кеше на диске в предварительно скомпилированном виде, чтобы избежать необходимости выполнять компиляции регулярных выражений при каждом импорте?

Не легко. Вам придется написать собственный сериализатор, который подключается к C sre реализации механизма регулярных выражений Python. Любые преимущества в производительности будут значительно перевешиваться затратами времени и усилий.

Во-первых, вы действительно профилировали код? Я сомневаюсь, что компиляция регулярных выражений является значительной частью времени выполнения приложения. Помните, что они компилируются только при первом импорте модуля в текущем выполнении — после этого модуль и его атрибуты кэшируются в памяти.

Если у вас есть программа, которая в основном создается один раз, компилирует кучу регулярных выражений, а затем завершает работу, вы можете попробовать перепроектировать ее для выполнения нескольких тестов за один вызов. Затем вы можете повторно использовать регулярные выражения, как указано выше.

Наконец, вы можете скомпилировать регулярные выражения в конечные автоматы на основе C, а затем связать их с модулем расширения. Хотя это, вероятно, будет сложнее поддерживать, это полностью устранит компиляцию регулярных выражений из вашего приложения.

person John Millikin    schedule 15.09.2008

Обратите внимание, что каждый модуль инициализируется только один раз в течение жизни приложения, независимо от того, сколько раз вы его импортируете. Поэтому, если вы компилируете свои выражения в глобальной области видимости модуля (т. е. не в функции), все должно быть в порядке.

person Toni Ruža    schedule 15.09.2008

Во-первых, это явное ограничение в модуле python re. Это накладывает ограничение на то, насколько и насколько велики регулярные выражения. Предел больше для длительных процессов и меньше для недолговечных процессов, таких как приложения командной строки.

Несколько лет назад я смотрел на это, и можно было выкопать результат компиляции, распарить его, а затем распаковать и использовать повторно. Проблема в том, что для этого требуется использование внутренних компонентов sre.py, поэтому, вероятно, они не будут работать в разных версиях Python.

Я хотел бы иметь такую ​​функцию в своем наборе инструментов. Я также хотел бы знать, есть ли какие-либо отдельные модули, которые можно было бы использовать вместо этого.

person iny    schedule 28.12.2008

Модуль shelve работает нормально:


import re
import shelve
a_pattern = "a.*b"
b_pattern = "c.*d"
a = re.compile(a_pattern)
b = re.compile(b_pattern)

x = shelve.open('re_cache')
x[a_pattern] = a
x[b_pattern] = b
x.close()

# ...
x = shelve.open('re_cache')
a = x[a_pattern]
b = x[b_pattern]
x.close()

Затем вы можете создать хороший класс-оболочку, который автоматически обрабатывает кэширование для вас, чтобы он стал прозрачным для пользователя... упражнение, оставленное читателю.

person Pat Notz    schedule 15.09.2008
comment
Модуль shelve использует pickle внутри. Шаблоны все равно будут перекомпилированы при загрузке их с полки. - person John Millikin; 15.09.2008

Откройте /usr/lib/python2.5/re.py и найдите «def _compile». Вы найдете внутренний механизм кэширования re.py.

person Community    schedule 15.09.2008

Можно поместить каждое регулярное выражение (или группу регулярных выражений) в отдельный файл, а затем динамически импортировать нужный файл с помощью модуля imp. Я сомневаюсь, что он очень хорошо масштабируется, но это может быть то, что вам нужно.

person David Locke    schedule 15.09.2008
comment
Регулярное выражение все равно нужно будет скомпилировать, явно или неявно, а это требует времени. - person Tal Weiss; 01.07.2010

Гум,

Разве полка не использует рассол?

В любом случае, я согласен с предыдущими ответчиками. Поскольку модуль обрабатывается только один раз, я сомневаюсь, что компиляция регулярных выражений станет узким местом вашего приложения. И модуль Python re работает очень быстро, так как он написан на C :-)

Но хорошая новость заключается в том, что у Python есть хорошее сообщество, поэтому я уверен, что вы можете найти кого-то, кто в настоящее время занимается взломом именно того, что вам нужно.

Я гуглил 5 секунд и нашел: http://home.gna.org/oomadness/en/cerealizer/index.html.

Не знаю, получится ли, но если нет, удачи в исследованиях :-)

person e-satis    schedule 15.09.2008