在外部文件中存储字典,正则表达式和变量的最佳方法?

时间:2019-01-27 13:40:25

标签: python json python-3.x configuration-files

出于配置目的,如果我将一个“简单”的正则表达式存储在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))

错误通常是相同的,这使我的在线搜索指向regular expressions should not be stored in JSON个文件。

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

YAML文件似乎有similar limitations,所以我不应该以这种方式崩溃。

现在,我已将表达式存储在字典中的单独文件中:

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 :(得分:2)

您指定的链接是JSON规范。据我所知,它没有对正则表达式说什么。

您似乎正在做的是获取一个正则表达式并将其粘贴到JSON文件中以供(重新)使用。但这并不总是可行的,因为必须使某些内容转义以使JSON有效。

不过,有一种简单的方法,可以通过制作一个小型Python程序将正则表达式插入到JSON文件中,并进行适当的转义,该程序将正则表达式作为命令行参数,然后{ {1}} JSON文件,或者使用新的正则表达式对文件进行load-update-dump。

答案 1 :(得分:1)

首先,正则表达式可以存储为JSON,但需要存储为有效JSON。这是您在示例中 var infoQuery = (from r in db.tbRecipe join s in db.tbCategory on r.CategoryID equals s.ID group new { r, s } by new { r.ID,r.CaloryValue,r.CategoryID,r.CoockTime,r.ImageList,r.Name,r.VideoURL , s.CategoryName } into grp select new { grp.Key.CategoryName, grp.Key.ID, grp.Key.ImageList, grp.Key.Name, grp.Key.CaloryValue, grp.Key.CoockTime, }).GroupBy(g => g.CategoryName, g => g) .Select(g => g.Take(10)); 的原因。

SO上还有其他答案,它们解释了如何正确地将正则表达式编码/解码为有效的JSON,例如: Escaping Regex to get Valid JSON

现在,您的问题的其他部分开始涉及更多最佳实践和意见。

如您所见,您当然可以声明并使用其他文件中的变量:

JSONDecodeError

test_regex.py

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

script.py

但是,这是一个完全不同的感觉用例。在我们的JSON示例中,信息的设置方式使我们希望它更易于配置-可以使用不同的正则表达式使用不同的JSON文件(也许用于不同的环境配置)。在此示例中,我们不假设可配置性,而是使用from test_regex import mydict mydict {'allow': 'com\\/[a-z]+(?:-[a-z]+)*\\?skid\\='} 来分离关注点和可读性。

答案 2 :(得分:0)

如果要将字典存储在.py文件中,则可以直接导入变量,只要可以找到文件in your PYTHONPATH或使用relative import

例如,如果我制作一个名为removerateplan(rateplan, i) { this.selectedRateplans = this.selectedRateplans.splice(i, 1); this.snackBar.open(rateplan.name + ' removed', 'close', { duration: 3000, }); } 的.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='>

解释器:

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}