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

StackOverflow https://stackoverflow.com/questions/65266

  •  09-06-2019
  •  | 
  •  

Вопрос

Каждый раз, когда импортируется файл 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
Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

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

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

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

А полка модуль, похоже, работает нормально:


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()

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

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

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

Хм,

Разве на полке не используются маринованные огурцы?

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top