2009-12-08 10 views
1

Je suis en train d'analyser un fichier avec python et pyparsing (c'est le fichier de rapport pour PSAT dans Matlab mais ce n'est pas important). here est ce que j'ai jusqu'à présent. Je pense que c'est un gâchis et voudrais des conseils sur la façon de l'améliorer. Plus précisément, comment dois-je organiser mes définitions de grammaire avec pyparsing?Comment devrais-je organiser mes fonctions avec pyparsing?

Devrais-je avoir toutes mes définitions de grammaire dans une fonction? Si c'est le cas, ça va être une énorme fonction. Sinon, comment puis-je le briser. En ce moment, je l'ai divisé dans les sections du fichier. Vaut-il la peine de faire plein de fonctions qui ne sont appelées qu'une seule fois d'un endroit? Ni l'un ni l'autre ne me semble vraiment juste.

Dois-je placer tout mon code d'entrée et de sortie dans un fichier séparé pour les autres fonctions de classe? Cela rendrait le but de la classe beaucoup plus clair.

Je suis également intéressé de savoir s'il existe un moyen plus simple d'analyser un fichier, de faire des vérifications de sécurité et de stocker les données dans une classe. J'ai l'impression de passer beaucoup de temps à faire ça.

(je vais accepter les réponses de il est assez bon ou utiliser X plutôt que pyparsing si les gens sont d'accord)

Répondre

2

je pourrais aller de toute façon à l'aide d'une seule grande méthode pour créer votre analyseur par rapport à prendre par étapes comme vous l'avez maintenant.

Je peux voir que vous avez défini quelques utilitaires auxiliaires utiles, tels que fente ("supprimer Literal", je présume), stringtolits, et decimaltable. Cela me semble bon. J'aime que vous utilisiez des noms de résultats, ils améliorent vraiment la robustesse de votre code post-analyse. Je recommande d'utiliser le formulaire raccourci qui a été ajouté dans pyparsing 1.4.7, dans lequel vous pouvez remplacer

busname.setResultsName("bus1") 

avec

busname("bus1") 

Cela peut désencombrer votre code un peu. Je regarderais en arrière dans vos actions d'analyse pour voir où vous utilisez des index numériques pour accéder aux jetons individuels, et revenir en arrière et assigner des noms de résultats à la place. Voici un cas, où GetStats renvoie (ngroup + sgroup).setParseAction(self.process_stats). process_stats a des références comme:

self.num_load = tokens[0]["loads"] 
self.num_generator = tokens[0]["generators"] 
self.num_transformer = tokens[0]["transformers"] 
self.num_line = tokens[0]["lines"] 
self.num_bus = tokens[0]["buses"] 
self.power_rate = tokens[1]["rate"] 

J'aime que vous avez Group'ed les valeurs et les statistiques, mais allez-y et leur donner des noms, comme « réseau » et « soln ». Ensuite, vous pouvez écrire ce code d'action d'analyse syntaxique comme (je l'ai aussi converti au - me - plus facile à lire la notation-attribut objet au lieu de la notation élément dict):

self.num_load = tokens.network.loads 
self.num_generator = tokens.network.generators 
self.num_transformer = tokens.network.transformers 
self.num_line = tokens.network.lines 
self.num_bus = tokens.network.buses 
self.power_rate = tokens.soln.rate 

En outre, une question de style: pourquoi utilisez-vous parfois le constructeur explicite And, au lieu d'utiliser l'opérateur '+'?

busdef = And([busname.setResultsName("bus1"), 
      busname.setResultsName("bus2"), 
      integer.setResultsName("linenum"), 
      decimaltable("pf qf pl ql".split())]) 

C'est tout aussi bien écrit:

busdef = (busname("bus1") + busname("bus2") + 
      integer("linenum") + 
      decimaltable("pf qf pl ql".split())) 

Dans l'ensemble, je pense que cela est à propos par un fichier de cette complexité.J'ai un format similaire (propriétaire, malheureusement, ne peut donc pas être partagée) dans lequel je construit le code en morceaux similaires à la façon dont vous avez, mais dans une grande méthode, quelque chose comme ceci:

def parser(): 
    header = Group(...) 
    inputsummary = Group(...) 
    jobstats = Group(...) 
    measurements = Group(...) 
    return header("hdr") + inputsummary("inputs") + jobstats("stats") + measurements("meas") 

Les constructions du groupe sont particulièrement utiles dans un grand analyseur comme celui-ci, pour établir une sorte d'espace de noms pour les noms de résultats dans chaque section des données analysées.

+0

Juste le genre de réponse que je cherchais. Le raccourci du nom rendra les choses plus belles. la notation d'objet-attribut est nouvelle pour moi; ça marche avec tous les dicts? de toute façon, merci. J'ai utilisé et parce que quand j'ai écrit ces parties j'ai oublié la continuation de la ligne implicite entre parenthèses. Je pense avoir PSATReport_IO en tant que classe séparée, il n'y a vraiment pas beaucoup d'autres fonctions qui sont nécessaires et il semble trop encombré. –

+0

dd = dict (zip ("a b c d" .split(), plage (4))); dd.a; dd ["a"] Non, cela ne fonctionne pas. Bonne syntaxe cependant. Je pourrais avoir à essayer de l'implémenter dans une classe dict personnalisée. –

+0

Non, le référencement de style d'attribut d'objet est une caractéristique de ParseResults de pyparsing, introuvable dans les dicts Python standard. Comme un point de données supplémentaire, mon analyseur pour le format propriétaire est d'environ 900 lignes. – PaulMcG