Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1475 connectés 

  FORUM HardWare.fr
  Programmation
  Python

  Erreur Nonetype sur une regexp pourtant reconnue [résolu]

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Erreur Nonetype sur une regexp pourtant reconnue [résolu]

n°1891739
Fourgueule
Posté le 05-06-2009 à 16:29:49  profilanswer
 

Bonjour à tous!
C'est mon premier post sur un forum de ce type, alors dîtes moi si quelque chose ne va pas (j'ai survolé http://forum.hardware.fr/hfr/Progr [...] 0261_1.htm mais on sait jamais).
D'habitude un peu de recherche sur google suffit mais sur le cas que je rencontre, j'avoue être plus que perplexe.
Je m'explique:
 
Je rencontre une erreur du type: AttributeError: 'NoneType' object has no attribute 'group' , le genre d'erreur qui m'arrive quand mon expression régulière n'est pas correcte et que temp.group(x) n'est pas définit (exemple de reconnaissance: temp=re.match(r"^(.+)", ligne) ). Bon.
 
Sauf qu'ici...
 

Code :
  1. print entree
  2. temp=re.match(r"ID=(.+)\s+SMILES=(.+)\s+NAME=(.+)", entree)
  3. print temp.group(1)+"\n"+temp.group(2)+"\n"+temp.group(3)


me renvoye:
 
ID=SPM SMILES=C(CCNCCCN)CNCCCN NAME=SPERMINE
SPM
C(CCNCCCN)CNCCCN
SPERMINE
 
Traceback (most recent call last):
  File "start_tanimoto_final.py", line 164, in <module>
    myapp = StartQT4()
  File "start_tanimoto_final.py", line 53, in __init__
    self.charger_fichier_1()
  File "start_tanimoto_final.py", line 86, in charger_fichier_1
    print temp.group(1)+"\n"+temp.group(2)+"\n"+temp.group(3)
AttributeError: 'NoneType' object has no attribute 'group'
 
(La reconnaissance d'expression étant située dans la méthode charger_fichier_1 de la classe StartQT4)
 
Donc si je résume, il m'imprime bien mes valeurs, mais s'arrête parce qu'elles ne seraient pas définies...  :sweat:
 
La piste que je privilégie, si ça peut vous aider :
Je me demande si ça ne viendrait pas de la façon dont entree est définie, je m'explique:
entree est une variable temporaire, utilisée pour parser le tableau Ligand_info_temp

Code :
  1. for entree in Ligand_info_temp


tableau crée par l'utilisation d'une méthode qui émule la fonction split de perl (fonction qui découpe un string selon un patern et qui renvoye un tableau):

Code :
  1. Ligand_info_temp=split( '\\\\', temp.group(2))


Le code de la méthode split est le suivant:  

Code :
  1. def split( pattern, string ):
  2.     o = re.compile( pattern )
  3.     result = []
  4.     curResult = o.search( string )
  5.     while curResult and string:
  6.         start, stop = curResult.span(0)
  7.         result.append(string[:start])
  8.         string = string[stop:]
  9.         curResult = o.search( string )
  10.     result.append( string )
  11.     return result


Y aurait t'il quelque chose qui n'irait pas dans cette méthode?  
Je me pose la question parce que quand je code en dur entree="ID=tralala SMILES=youpi NAME=youplaboum", l'expression régulière fonctionne correctement, et en plus aucune erreur n'a lieu.
 
Ou est ce que cela viendrait d'autre part? Dans le pire des cas, peut on forcer Python à continuer l'execution du script même en cas d'erreur, puisque finalement les valeurs reconnues par l'expression régulière sont celles que je veux? Merci d'avance pour votre aide.


Message édité par Fourgueule le 08-06-2009 à 16:11:44
mood
Publicité
Posté le 05-06-2009 à 16:29:49  profilanswer
 

n°1891761
masklinn
í dag viðrar vel til loftárása
Posté le 05-06-2009 à 17:05:38  profilanswer
 

Avant de passer au problème même, petites suggestions:

 

1. Poster du code python en utilisant la balise [ code=python] (en enlevant l'espace au début qui est là pour éviter que le forum ne me l'interprète et non la balise [ code] ou  [ cpp], ça donne une coloration correcte:

 
Code :
  1. def split( pattern, string ):
  2.    o = re.compile( pattern )
  3.    result = []
  4.    curResult = o.search( string )
  5.    while curResult and string:
  6.        start, stop = curResult.span(0)
  7.        result.append(string[:start])
  8.        string = string[stop:]
  9.        curResult = o.search( string )
  10.    result.append( string )
  11.    return result


vs

Code :
  1. def split( pattern, string ):
  2.     o = re.compile( pattern )
  3.     result = []
  4.     curResult = o.search( string )
  5.     while curResult and string:
  6.         start, stop = curResult.span(0)
  7.         result.append(string[:start])
  8.         string = string[stop:]
  9.         curResult = o.search( string )
  10.     result.append( string )
  11.     return result
 

2. La PEP8 demande de ne pas mettre d'espaces entre les parentèses: def split(pattern, string) non def split( pattern, string ), o.search(string) et non o.search( string )

 

3. J'ai un peu de mal à voir l'intérêt de ta fonction split quand au pire elle fait ce que fait str.split et au mieux ce que fait re.split [:petrus75] (accessoirement les rawstrings ne sont pas limités aux regexps...)

 

4. print permet de séparer les valeurs qu'on lui donne par des virgules, print temp.group(1), "\n", temp.group(2), "\n", temp.group(3) est quand même plus lisible.

 

Pour ton problème, il faudrait plus d'infos, parce que là c'est pas reproductible. Si tu utilises un vrai split ça donne quoi? Les données viennent d'où? Fichier? Il est possible de voir tout ou partie du fichier?

 

Là comme ça je dirais de vérifier que tu ne récupères pas une ligne vide, ça concorderait (pas d'affichage parce que ton "print entree" sauterait simplement à la ligne, puis pas de match, et donc tu te prends des AttributeError).

 

Quand à essayer de planquer l'erreur sous le tapis et continuer le traitement... [:kiki]

 

Accessoirement, je suggérerais en plus de:
5. améliorer ton nommage de variables, là c'est vraiment pas terrible
6. utiliser des named match groups (directive ?P)
7. après un match/search, toujours tester que quelque chose a été matché au lieu de continuer direct sur l'utilisation du MatchObject


Message édité par masklinn le 05-06-2009 à 17:07:37

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1891941
Fourgueule
Posté le 06-06-2009 à 12:21:51  profilanswer
 

Tout d'abord merci de t'intéresser au problème Masklinn.
J'essayerai de suivre tes suggestions. Je ne savais pas pour la virgule dans le print, ça m'a l'air effectivement d'être une bonne chose.
La raison de la fonction split est que j'avais lu (en cherchant à faire un split en python) ceci: http://mail.python.org/pipermail/p [...] 0465.html. Mais maintenant que je le relis, je crois comprendre qu'il ne mettait le code du split qu'à titre d'exemple, puisqu'il propose ensuite une utilisation de re.split. Hum.
Bref aucune raison valable finalement.  :o  
 
Pour ce qui est tester le split de re il faudra que j'attende lundi pour être sur mon environnement de travail. Mais pour la ligne vide c'est sûrement ça! Je peux pas tester maintenant mais ça expliquerait des affichages que j'ai eu lors de mes tests que je ne comprenait pas alors. (Je n'avais envisagé cette possibilité qui me paraît évidente maintenant que tu l'évoques)
 
En ce qui concerne les données, oui je les tire d'un fichier, que j'ai créé à partir des infos sur http://www.rcsb.org/pdb/home/home.do. Données publiques donc, pas de problème pour les montrer:
 
100d\"ID=SPM SMILES=C(CCNCCCN)CNCCCN NAME=SPERMINE\"\HEADER=DNA-RNA\TITLE=CRYSTAL STRUCTURE OF THE HIGHLY DISTORTED CHIMERIC DECAMER R(C)D(CGGCGCCG)R(G)-SPERMINE COMPLEX-SPERMINE BINDING TO PHOSPHATE ONLY AND MINOR GROOVE TERTIARY BASE-PAIRING  
200l\"ID=BME SMILES=C(CS)O NAME=BETA-MERCAPTOETHANOL\ID=CL SMILES=[Cl-] NAME=CHLORIDEION\"\HEADER=HYDROLASE\TITLE=THERMODYNAMIC AND STRUCTURAL COMPENSATION IN "SIZE-SWITCH" CORE-REPACKING VARIANTS OF T4 LYSOZYME  
300d\"ID=MN SMILES=[Mn+2] NAME=MANGANESE(II)ION\"\HEADER=RIBOZYME\TITLE=CAPTURING THE STRUCTURE OF A CATALYTIC RNA INTERMEDIATE: RNA HAMMERHEAD RIBOZYME, MN(II)-SOAKED  
400d\"ID=5CM SMILES=CC1=CN(C(=O)N=C1N)[C@H]2C[C@@H]([C@H](O2)COP(=O)(O)O)O NAME=5-METHYL-2'-DEOXY-CYTIDINE-5'-MONOPHOSPHATE\"\HEADER=DNA\TITLE=THE INTRINSIC STRUCTURE AND STABILITY OF OUT-OF-ALTERNATION BASE PAIRS IN Z-DNA  
101d\"ID=NT SMILES=Cn1cc(cc1C(=O)Nc2cc(n(c2)C)C(=O)NCCC(=N)N)NC(=O)CNC(=N)N NAME=NETROPSIN\ID=MG SMILES=[Mg+2] NAME=MAGNESIUMION\ID=CBR SMILES=C1[C@@H]([C@H](O[C@H]1N2C=C(C(=NC2=O)N)Br)COP(=O)(O)O)O NAME=5-BROMO-2'-DEOXY-CYTIDINE-5'-MONOPHOSPHATE\"\HEADER=DNA\TITLE=REFINEMENT OF NETROPSIN BOUND TO DNA: BIAS AND FEEDBACK IN ELECTRON DENSITY MAP INTERPRETATION  
 
Je dirais que le code minimal (pour ceux qui veulent tester) doit être quelque chose dans le goût là:
 

Code :
  1. def split(pattern, string):
  2.    o = re.compile(pattern)
  3.    result = []
  4.    curResult = o.search(string)
  5.    while curResult and string:
  6.        start, stop = curResult.span(0)
  7.        result.append(string[:start])
  8.        #result.append(string[start:stop])
  9.        string = string[stop:]
  10.        curResult = o.search(string)
  11.    result.append(string)
  12.    return result
  13.  
  14. Ligand_info_temp=[];
  15.  
  16. lignes = codecs.open('PDB_Smiles_test.txt','r','utf-8').readlines()
  17. for ligne in lignes:
  18.     ligne=ligne.rstrip('\n')
  19.     temp=re.match(r"^(.+)\\\"(.+)\"\\HEADER=(.*)\\TITLE=(.*)$", ligne)
  20.     Ligand_info_temp=split( '\\\\', temp.group(2))
  21.  
  22.     for entree in Ligand_info_temp:
  23.         print entree
  24.         temp=re.match(r"^ID=(.+)\s+SMILES=(.+)\s+NAME=(.+)$", entree)
  25.         print temp.group(1),"\n",temp.group(2),"\n",temp.group(3)


Pour le named match groups, euh, je ne sais tout simplement pas ce que c'est, mais je promets de me renseigner sur le sujet.
Le nom de mes variables est la seule chose sur laquelle je ne promet rien  ;) (mais je ferais un peu plus d'efforts à l'avenir).

n°1891946
masklinn
í dag viðrar vel til loftárása
Posté le 06-06-2009 à 12:55:31  profilanswer
 

Dans la mesure où ce sont des données bio disponibles dans des formats relativement standard (je présume), tu as essayé de regarder s'il n'y avait pas déjà des libs capables d'en lire un ou 2 (genre scipy.io)?

 

Sinon, autres problèmes que je vis dans ton bout de code:

 

1. Reste cohérent dans ton nommage de variables, de préférence en anglais
2. Pas besoin de "readlines", les objets fichiers sont itérables en Python donc tu peux écrire directement

Code :
  1. for line in codecs.open('file.txt', 'r', 'utf-8')


3.

Code :
  1. Ligand_info_temp=[];


ne sert à rien (aussi bien le ";" que le reste de la ligne)
4.

Code :
  1. temp=re.match(r"^(.+)\\\"(.+)\"\\HEADER=(.*)\\TITLE=(.*)$", ligne)


Tu pourrais te simplifier le boulot en écrivant:

Code :
  1. temp = re.match(r'''^(.+)\\"(.+)"\\HEADER=(.*)\\TITLE=(.*)$''', line)


histoire de ne pas avoir à échapper tes quotes et doubles quotes.

 

Accessoirement, tu peux mettre le rstrip directement dans le paramètre:

Code :
  1. temp = re.match(r'''^(.+)\\"(.+)"\\HEADER=(.*)\\TITLE=(.*)$''', line.rstrip())


et par défaut rstrip enlève tout le whitespace (espaces, tabs, newlines), pas besoin de préciser newlines donc (sauf si tu veux garder les espaces mais bon...)

 

5. Les named matchgroup permettent de référencer une match par un nom plutôt que par un indice (de cette manière même si tu dois éditer ta regex et rajouter des matchgroups ça ne pète pas, et accessoirement c'est plus lisible):

Code :
  1. >>> import re
  2. >>> s = "blabla[someinfo]whatever{some other info}"
  3. >>> m = re.match(r'^[\w\s]+\[(?P<info0>[^\]]+)\][\w\s]+\{(?P<info1>[^\}]+)\}$', s)
  4. >>> m
  5. <_sre.SRE_Match object at 0x62a968>
  6. >>> m.group('info0')
  7. 'someinfo'
  8. >>> m.group('info1')
  9. 'some other info'


cf documentation Python sur le module re.


Message édité par masklinn le 06-06-2009 à 12:56:33

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1892633
Fourgueule
Posté le 08-06-2009 à 16:10:10  profilanswer
 

Je parse des données que j'ai été cherché un peu partout sur le site en fait, donc aucun script n'existe pour les parser.
 
Sinon j'ai reformaté mes données dans un format plus simple (deux fichiers), le code en est d'autant plus clair, et surtout il marche en utilisant re.split.
C'est vrai qu'il faut faire attention en cas de reconnaissance d'expression en début ou en fin de string, parce que ça renvoie un string vide dans le tableau.
J'ai plus qu'à appliquer le tag résolu sur ce topic... quand j'aurai trouvé comment il faut faire.  :o  
(Edit, j'ai changé le titre... c'est tout ce que je dois faire ou y a t'il une procédure spéciale?)
 
Merci pour tous tes conseils Masklinn, j'appliquerai des named matchgroup à l'avenir.


Message édité par Fourgueule le 08-06-2009 à 16:12:49

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Python

  Erreur Nonetype sur une regexp pourtant reconnue [résolu]

 

Sujets relatifs
[Resolu][ASP.NET] deployement sur serveur IIS / pb de bibliothequeErreur requête SQL en VBA dans Excel
[Résolu] aide requête SQL: tri par date desc avec date "nulle" en 1erErreur d'exécution '53': Fichier introuvable
[Résolu-BATCH] aide sur la commande for /f delims[Resolu]Code qui passe toujours dans le IF
[RESOLU]Problème de lecture de fichier tout bêteRequete dans plusieurs tables [resolu]
[Resolu]Controle de saisie Adresse IP sur un formulaire[Résolu] Erreur incompréhensible...
Plus de sujets relatifs à : Erreur Nonetype sur une regexp pourtant reconnue [résolu]


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR