2
votes

Le meilleur moyen de stocker des dictionnaires, des expressions régulières et des variables dans un fichier externe?

À des fins de configuration, si je stocke une expression régulière "facile" dans un fichier JSON et que je la charge dans mon programme Python, cela fonctionne très bien.

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

print(mydict)

Si je stocke une expression régulière plus complexe dans un fichier JSON, le même programme Python échoue.

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

C'est le code qui charge mon fichier JSON:

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

et l'erreur est généralement la même, indiquant mes recherches en ligne sur le fait que les expressions régulières ne doivent stockés dans des fichiers JSON .

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

Les fichiers YAML semblent avoir limitations similaires , donc je ne devrais pas descendre de cette façon je suppose.

Maintenant, j'ai stocké mon expression dans un dict dans un fichier séparé :

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

et chargez-le depuis mon fichier programme:

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

Ce qui fonctionne et me conviendrait - mais ça semble un peu ... spécial ... avec exec et compile.

Y a-t-il une raison de ne pas le faire de cette façon? Existe-t-il un meilleur moyen de stocker des structures de données complexes et des expressions régulières dans des fichiers externes que je peux ouvrir / utiliser dans mon code de programme?


2 commentaires

Pensez à utiliser le module pickle de Python. Voir également Rendre l'objet JSON sérialisable avec un encodeur normal .


Notez que vous devez utiliser le préfixe de chaîne r pour les expressions regex (et ne pas le faire pourrait en fait être la cause de certains de vos problèmes de stockage).


3 Réponses :


2
votes

Le lien que vous indiquez est la spécification JSON. Autant que je sache, cela ne dit rien sur les expressions régulières.

Ce que vous semblez faire, c'est prendre une expression régulière fonctionnelle et la coller dans votre fichier JSON pour la (ré) utiliser. Et cela ne fonctionne pas toujours car certaines choses doivent être échappées pour que le JSON soit valide.

Il existe cependant un moyen simple d'insérer l'expression régulière dans le fichier JSON, avec les échappements appropriés , en créant un petit programme Python qui prendra l'expression régulière comme paramètre de ligne de commande, puis < code> json.dump () le fichier JSON ou, alternativement, load-update-dump le fichier avec la nouvelle expression régulière.


0 commentaires

1
votes

Premièrement, les expressions régulières peuvent être stockées au format JSON, mais doivent être stockées en tant que JSON valide. C'est la cause de votre JSONDecodeError dans l'exemple.

Il y a d'autres réponses ici sur SO, qui expliquent comment correctement encoder / décoder les regex en tant que JSON valide, telles que: Échapper à Regex pour obtenir un JSON valide

Maintenant, le d'autres éléments de votre question commencent à porter sur davantage de bonnes pratiques et d'opinions.

Comme vous l'avez vu, vous pouvez certainement déclarer et utiliser des variables d'autres fichiers:

test_regex.py

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


0 commentaires

0
votes

Si vous stockez votre dictionnaire dans un fichier .py, vous pouvez importer la variable directement tant que le fichier peut être trouvé dans votre PYTHONPATH ou vous utilisez un importation relative .

Par exemple, si je crée un fichier .py appelé expr.py et PYTHONPATH inclut le dossier c'est dedans.

Le contenu du fichier (identique à votre exemple):

>>> 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\\=')}

Ensuite, je peux l'exécuter à partir d'un interpréteur ou d'un autre script p>

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}

Pas besoin de jouer avec open () et exec sauf si je manque quelque chose ici. J'utilise cette approche pour stocker les expressions régulières car vous pouvez stocker des objets re.compile directement.

si je change le fichier en:

>>> 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='>

Je peux faire:

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

si le fichier contient une quantité idiote d'expressions régulières, le tri automatique des variables sous le nom du script pourrait également aider à l'organisation: p >

fichier:

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

interpréteur:

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


0 commentaires