Лучший способ хранить DICT, регулярные выражения и переменные во внешнем файле? - PullRequest
0 голосов
/ 27 января 2019

В целях конфигурации, если я храню «легкое» регулярное выражение в файле JSON и загружаю его в свою программу на Python, он работает просто отлично.

{
    "allow": ["\/word\/.*"],
    "follow": true
},

Если я храню более сложное регулярное выражениев файле JSON происходит сбой той же самой программы Python.

{
    "allow": ["dcp\=[0-9]+\&dppp\="],
    "follow": true
},

Это код, который загружает мой файл JSON:

src_json = kw.get('src_json') or 'sources/sample.json'
self.MY_SETTINGS = json.load(open(src_json))

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

json.decoder.JSONDecodeError: Invalid \escape: line 22 column 38 (char 801)

Файлы YAML, похоже, имеют аналогичные ограничения , поэтому я не должен получатьтаким образом, я думаю.

Теперь я сохранил свое выражение внутри dict в отдельном файле:

mydict = {"allow": "com\/[a-z]+(?:-[a-z]+)*\?skid\="}

и загрузил его из моего программного файла:

exec(compile(source=open('expr.py').read(), filename='expr.py', mode='exec'))

print(mydict)

Что работает и будет хорошо со мной - но это выглядит немного ... особенным ... с exec и compile.

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

Ответы [ 3 ]

0 голосов
/ 27 января 2019

Во-первых, регулярные выражения могут быть сохранены как JSON, но должны быть сохранены как допустимые JSON. Это причина вашего JSONDecodeError в примере.

Здесь, на SO, есть другие ответы, объясняющие, как правильно кодировать / декодировать регулярные выражения в качестве допустимого JSON, например: Egeing Regex, чтобы получить действительный JSON

Теперь другие части вашего вопроса начинают углубляться в лучшие практики и мнения.

Как вы уже видели, вы, безусловно, можете объявлять и использовать переменные из других файлов:

test_regex.py

my_dict = {'allow': 'com\\/[a-z]+(?:-[a-z]+)*\\?skid\\='}

script.py

from test_regex import mydict
mydict
{'allow': 'com\\/[a-z]+(?:-[a-z]+)*\\?skid\\='}

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

0 голосов
/ 27 января 2019

Если вы храните свой словарь в файле .py, вы можете импортировать переменную напрямую, если файл может быть найден в вашем PYTHONPATH или вы используете относительный импорт .

Например, если я создаю файл .py с именем expr.py, а PYTHONPATH включает папку, в которой он находится.

Содержимое файла (аналогично вашему примеру):

mydict = {"allow": "com\/[a-z]+(?:-[a-z]+)*\?skid\="}

Тогда я могу запустить это из интерпретатора или другого скрипта

>>> from expr import mydict
>>> mydict
{'allow': 'com\\/[a-z]+(?:-[a-z]+)*\\?skid\\='}

Нет необходимости возиться с open() и exec, если я не пропустил что-то здесь.Я использую этот подход для хранения регулярных выражений, потому что вы можете хранить re.compile объектов напрямую.

, если я изменю файл на:

import re
mydict = {"allow": re.compile(r"com\/[a-z]+(?:-[a-z]+)*\?skid\=")}

Я могу сделать:

>>> from expr import mydict
>>> print(mydict)
{'allow': re.compile('com\\/[a-z]+(?:-[a-z]+)*\\?skid\\=')}
>>> print(mydict["allow"].pattern)
com\/[a-z]+(?:-[a-z]+)*\?skid\=
>>> print(mydict["allow"].match("com/x-x?skid="))
<_sre.SRE_Match object; span=(0, 13), match='com/x-x?skid='>

если в файле содержится много глупых регулярных выражений, автоматическая сортировка переменных по имени сценария также может помочь с организацией:

file:

import re
mydict = {"allow": re.compile(r"com\/[a-z]+(?:-[a-z]+)*\?skid\=")}
easydict = {"allow": re.compile(r"\/word\/.*"), "follow": True}
complexdict = {"allow": re.compile(r"dcp\=[0-9]+\&dppp\="), "follow": True}

интерпретатор:

>>> import expr
>>> print(expr.easydict["allow"].pattern)
\/word\/.*
>>> print(expr.complexdict["allow"].match("dcp=11&dppp="))
<_sre.SRE_Match object; span=(0, 12), match='dcp=11&dppp='>
>>> print(expr.mydict)
{'allow': re.compile('com\\/[a-z]+(?:-[a-z]+)*\\?skid\\=')}
0 голосов
/ 27 января 2019

Указанная вами ссылка является спецификацией JSON.Насколько я могу судить, он ничего не говорит о регулярных выражениях.

То, что вы, похоже, делаете, - это взятие рабочего регулярного выражения и вставка его в файл JSON для (повторного) использования.И это не всегда работает, потому что некоторые вещи нужно экранировать, чтобы JSON был действительным.

Однако существует простой способ вставить регулярное выражение в файл JSON, с соответствующимэкранируется , создав небольшую программу на Python, которая будет принимать регулярное выражение в качестве параметра командной строки, а затем json.dump() файл JSON или, альтернативно, загрузить-обновить-выгрузить файл с новым регулярным выражением.

...