在外部文件中存储字典、正则表达式和变量的最佳方式?
Best way to store dicts, regex and variables in external file?
出于配置目的,如果我将 "easy" 正则表达式存储在 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 和编译。
有什么理由不这样做呢?
有没有更好的方法在我可以在我的程序代码中打开/使用的外部文件中存储复杂的数据结构和正则表达式?
您指定的link是JSON规格。据我所知,它没有说明正则表达式。
您似乎在做的是采用有效的正则表达式并将其粘贴到您的 JSON 文件中以供(重新)使用。这并不总是有效,因为必须转义某些内容才能使 JSON 有效。
然而,有一种简单的方法可以将正则表达式插入 JSON 文件,使用适当的转义符 ,方法是制作一个小的 Python 程序这会将正则表达式作为命令行参数,然后 json.dump()
JSON 文件,或者,使用新的正则表达式加载-更新-转储文件。
首先,正则表达式可以存储为JSON,但需要存储为有效的JSON。这就是您在示例中 JSONDecodeError
的原因。
SO 上还有其他答案,解释了如何正确 encode/decode 正则表达式作为有效 JSON,例如:
Escaping Regex to get Valid JSON
现在,您问题的其他部分开始涉及更多最佳实践和意见。
- 您可以将 JSON 用于字典、正则表达式和变量吗?
- 是
- JSON理想吗?
- 取决于您的用例
- What is JSON and why would I use it?
如您所见,您当然可以声明和使用来自其他文件的变量:
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
用于关注点分离和可读性。
如果您将字典存储在 .py 文件中,只要可以找到该文件,您就可以直接导入变量 in your PYTHONPATH
or you use a relative import。
例如,如果我创建一个名为 expr.py
的 .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}
口译员:
>>> 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\=')}
出于配置目的,如果我将 "easy" 正则表达式存储在 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 和编译。
有什么理由不这样做呢? 有没有更好的方法在我可以在我的程序代码中打开/使用的外部文件中存储复杂的数据结构和正则表达式?
您指定的link是JSON规格。据我所知,它没有说明正则表达式。
您似乎在做的是采用有效的正则表达式并将其粘贴到您的 JSON 文件中以供(重新)使用。这并不总是有效,因为必须转义某些内容才能使 JSON 有效。
然而,有一种简单的方法可以将正则表达式插入 JSON 文件,使用适当的转义符 ,方法是制作一个小的 Python 程序这会将正则表达式作为命令行参数,然后 json.dump()
JSON 文件,或者,使用新的正则表达式加载-更新-转储文件。
首先,正则表达式可以存储为JSON,但需要存储为有效的JSON。这就是您在示例中 JSONDecodeError
的原因。
SO 上还有其他答案,解释了如何正确 encode/decode 正则表达式作为有效 JSON,例如: Escaping Regex to get Valid JSON
现在,您问题的其他部分开始涉及更多最佳实践和意见。
- 您可以将 JSON 用于字典、正则表达式和变量吗?
- 是
- JSON理想吗?
- 取决于您的用例
- What is JSON and why would I use it?
如您所见,您当然可以声明和使用来自其他文件的变量:
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
用于关注点分离和可读性。
如果您将字典存储在 .py 文件中,只要可以找到该文件,您就可以直接导入变量 in your PYTHONPATH
or you use a relative import。
例如,如果我创建一个名为 expr.py
的 .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}
口译员:
>>> 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\=')}