OVH Cloud OVH Cloud

Exceptions en Python

11 réponses
Avatar
NonSenZ
Bonjour à tous,

J'essaie d'utiliser des exceptions dans une application python/GTK afin
que l'utilisateur final n'ait que des messages d'erreur dans des
fenêtres de dialogue, et non pas dans la console qu'il n'aura d'ailleurs
pas ouverte. Pour télécharger un fichier sur le web depuis mon
programme GTK, j'utilise les modules urllib et httplib.
Ma méthode de téléchargement commence ainsi :

def get_film_list(self):
#Try to connect, there could be errors
try:
conn = httplib.HTTPConnection(self.mcdomaine)
except:
alert = SimpleGladeApp("nszmoviecov.glade", "dialog1")
alertxt = u"Probl\u00E8me de connexion sur www.moviecovers.com"
alert.label11.set_text(alertxt)
return

Mais voilà, quand la connexion est coupée, l'exception n'est pas
déclenchée et j'ai un message d'erreur dans la console :

Traceback (most recent call last):
File "./nszgtkfilms.py", line 172, in on_telecharger1_activate
self.mvcov1.get_film_list()
File "/home/nonsenz/python/nszgtkfilms/moviecovers.py", line 34, in get_film_list
conn.request("GET",self.mctxtpath)
File "/usr/lib/python2.3/httplib.py", line 721, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python2.3/httplib.py", line 742, in _send_request
self.endheaders()
File "/usr/lib/python2.3/httplib.py", line 715, in endheaders
self._send_output()
File "/usr/lib/python2.3/httplib.py", line 600, in _send_output
self.send(msg)
File "/usr/lib/python2.3/httplib.py", line 567, in send
self.connect()
File "/usr/lib/python2.3/httplib.py", line 535, in connect
socket.SOCK_STREAM):
socket.gaierror: (-3, '\xc3\x89chec temporaire dans la r\xc3\xa9solution du nom')

Ok, connexion coupée donc pas de résolution DNS, mais pourquoi mon
exception ne fonctionne-t-elle pas ?
Je fais sans doute une erreur grossière, mais je ne vois pas laquelle...

--
NSZ

10 réponses

1 2
Avatar
bruno at modulix
NonSenZ wrote:
Bonjour à tous,

J'essaie d'utiliser des exceptions dans une application python/GTK afin
que l'utilisateur final n'ait que des messages d'erreur dans des
fenêtres de dialogue, et non pas dans la console qu'il n'aura d'ailleurs
pas ouverte. Pour télécharger un fichier sur le web depuis mon
programme GTK, j'utilise les modules urllib et httplib.
Ma méthode de téléchargement commence ainsi :

def get_film_list(self):
#Try to connect, there could be errors
try:
conn = httplib.HTTPConnection(self.mcdomaine)
except:
alert = SimpleGladeApp("nszmoviecov.glade", "dialog1")
alertxt = u"Problu00E8me de connexion sur www.moviecovers.com"
alert.label11.set_text(alertxt)
return


Exemple typique de code à éviter. J'ai une fois passer des heures à
m'arracher les cheveux sur un script qui renvoyais systématiquement un
message d'erreur... erroné !

Dans ton cas, tu devrais inspecter l'exception que tu attrapes, afficher
un message d'erreur explicite (généralement il y en a un dans
l'exception...), éventuellement proposer une solution possible à
l'utilisateur selon le type d'erreur, etc.

Egalement, relis la doc Python sur les exceptions: il y en a certaines
que tu ne souhaites pas forcément passer à la trappe (SysExit, au hasard...)

Mais voilà, quand la connexion est coupée, l'exception n'est pas
déclenchée et j'ai un message d'erreur dans la console :

Traceback (most recent call last):
File "./nszgtkfilms.py", line 172, in on_telecharger1_activate
self.mvcov1.get_film_list()
File "/home/nonsenz/python/nszgtkfilms/moviecovers.py", line 34, in get_film_list
conn.request("GET",self.mctxtpath)

Ok, connexion coupée donc pas de résolution DNS, mais pourquoi mon
exception ne fonctionne-t-elle pas ?


s/mon exception/ma gestion d'exception/

Et elle "fonctionne" très bien (pb évoqués ci-dessus à part).

Je fais sans doute une erreur grossière, mais je ne vois pas laquelle...


Celle de croire que placer l'appel au constructeur de
httplib.HTTPConnection dans un try/except aura un effet sur l'appel de
la méthode request sur l'objet connection....

L'interpréteur interactif Python est un très bon outil pour
explorer/prototyper. Les tests unitaires sont aussi un bon moyen de
vérifier que le code se comporte comme prévu, et de repérer la source du
problème le cas échéant...

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"

Avatar
NonSenZ
Le Tue, 01 Nov 2005 13:50:52 +0100, bruno at modulix a écrit :
Et elle "fonctionne" très bien (pb évoqués ci-dessus à part).

Je fais sans doute une erreur grossière, mais je ne vois pas laquelle...


Celle de croire que placer l'appel au constructeur de
httplib.HTTPConnection dans un try/except aura un effet sur l'appel de
la méthode request sur l'objet connection....

L'interpréteur interactif Python est un très bon outil pour
explorer/prototyper. Les tests unitaires sont aussi un bon moyen de
vérifier que le code se comporte comme prévu, et de repérer la source du
problème le cas échéant...
---

Cette réponse me convient tout à fait, après quand même quelques
heures à tourner tout ça dans ma tête et à faire des tests. Pour être
franc, dans un premier temps, j'ai cru que tu répondais à côté de la
question au début du post, et je me demandais si j'aurais assez que la
fin de ma vie pour en comprendre la fin. Et puis j'ai fini par comprendre
l'ensemble.
Je n'avais en effet pas catché l'exception car elle arrivait après la
construction.
Merci beaucoup en tous cas ! C'est un plaisir de côtoyer des gens qui
savent de quoi ils parlent.
Si vous avez des exemples de docs python qui parlent des exceptions, je
suis preneur. Les infos que j'ai récupérées proviennent d'un tutorial
de Guido van Rossum, Fred L. Drake, Jr, editor traduit par Olivier Berger
et Henri Garreta, mais je trouve quand même cette notion assez difficile
à maîtriser complètement...

--
NSZ


Avatar
Rémi

Et elle "fonctionne" très bien (pb évoqués ci-dessus à part).


Je fais sans doute une erreur grossière, mais je ne vois pas laquelle...


Celle de croire que placer l'appel au constructeur de
httplib.HTTPConnection dans un try/except aura un effet sur l'appel de
la méthode request sur l'objet connection....

L'interpréteur interactif Python est un très bon outil pour
explorer/prototyper. Les tests unitaires sont aussi un bon moyen de
vérifier que le code se comporte comme prévu, et de repérer la source du
problème le cas échéant...


---
Cette réponse me convient tout à fait, après quand même quelques
heures à tourner tout ça dans ma tête et à faire des tests. Pour être
franc, dans un premier temps, j'ai cru que tu répondais à côté de la
question au début du post, et je me demandais si j'aurais assez que la
fin de ma vie pour en comprendre la fin. Et puis j'ai fini par comprendre
l'ensemble.
Je n'avais en effet pas catché l'exception car elle arrivait après la
construction.
Merci beaucoup en tous cas ! C'est un plaisir de côtoyer des gens qui
savent de quoi ils parlent.
Si vous avez des exemples de docs python qui parlent des exceptions, je
suis preneur. Les infos que j'ai récupérées proviennent d'un tutorial
de Guido van Rossum, Fred L. Drake, Jr, editor traduit par Olivier Berger
et Henri Garreta, mais je trouve quand même cette notion assez difficile
à maîtriser complètement...



Un principe que j'adopte souvent c'est de ne rien catcher au début,
et d'ajouter les catchs d'exception au fur et à mesure qu'elles se
produisent, mais je ne catche que celles là et surtout je gère l'exception.

Pour les autres exception, si tu es dans une application graphique, tu
les laisses remonter jusqu'au sommet de l'application et tu les affiches
dans une fenêtre en montrant la pile d'appel, ainsi tu peux remonter
plus facilement jusqu'à la source de l'exception, pour la corriger, car
tu ne sais que rarement à l'avance quelle sont les exceptions que tu vas
avoir besoin, et gérer l'ensemble peux devenir fastidieux (on est pas en
java bon dieu).
Mais surtout ne jamais catcher une exception par 'except:', il faut
toujours y associer une classe, sinon une erreur de syntaxe peut
complètement passée inaperçue et là tu peux chercher des heures...

Pour trapper l'ensemble des exceptions, il faut créer ton propre
gestionnaire d'exception en remplacant la fonction stockée dans
"sys.excepthook", tu la remplace par une fenêtre texte affichant la pile
(voir la doc python). Quelque fois les librairies graphiques le
proposent, il me semble que wxPython a une classe de ce type.

Autre chose importante, quand tu crée tes propres classes, crée aussi
tes classes d'exception, avec une hierarchie exemple:

class TaClasse:
def .... etc

class ExceptionTaClasse(Exception): # Classe générique de l'exception
pass

class OverflowTaClasse(ExceptionTaClasse): # Classe spécialisée d'exception
...

class MissingValueTaClasse(ExceptionTaClasse): # Classe spécialisée
d'exception
....

Dans ta classe TaClasse, tu ne raise que des classes spécialisées
d'exception, par contre tu peux catcher une classe générique et ainsi
traiter l'ensemble de tes exceptions qui se produisent sur ta classe.
L'orientation objet est aussi importante à mettre sur les exceptions,
que sur le reste de l'application, malheureusement ce n'est pas toujours
fait...

J'espère être assez claire, pas évident à expliquer.

Voilà en espérant que cela t'aide.



Avatar
Bruno Desthuilliers

Et elle "fonctionne" très bien (pb évoqués ci-dessus à part).


Je fais sans doute une erreur grossière, mais je ne vois pas laquelle...


Celle de croire que placer l'appel au constructeur de
httplib.HTTPConnection dans un try/except aura un effet sur l'appel de
la méthode request sur l'objet connection....

L'interpréteur interactif Python est un très bon outil pour
explorer/prototyper. Les tests unitaires sont aussi un bon moyen de
vérifier que le code se comporte comme prévu, et de repérer la source du
problème le cas échéant...


---
Cette réponse me convient tout à fait,


<reverence>votre humble serviteur, Messire</reverence>

après quand même quelques
heures à tourner tout ça dans ma tête


Ya pourtant pas de quoi.

et à faire des tests.


Ce qui reste le meilleur moyen d'apprendre...

Pour être
franc, dans un premier temps, j'ai cru que tu répondais à côté de la
question au début du post,


En partie, dans la mesure où ça ne répondais pas à ta question, mais
attirait ton attention sur un problème qui t'avait échappé.

et je me demandais si j'aurais assez que la
fin de ma vie pour en comprendre la fin.


Ah ?

Et puis j'ai fini par comprendre
l'ensemble.
Je n'avais en effet pas catché l'exception car elle arrivait après la
construction.


Bin oui...

Merci beaucoup en tous cas ! C'est un plaisir de côtoyer des gens qui
savent de quoi ils parlent.
Si vous avez des exemples de docs python qui parlent des exceptions, je
suis preneur.


Tout texte introductif sur Python doit (devrait...) en parler. Regarde là:
http://fr.diveintopython.org/fileinfo_exception.html
ou là:
http://www.ulg.ac.be/cifen/inforef/swi/python.htm

Les infos que j'ai récupérées proviennent d'un tutorial
de Guido van Rossum, Fred L. Drake, Jr, editor traduit par Olivier Berger
et Henri Garreta,


Bref, la trad fr du tutoriel officiel...

mais je trouve quand même cette notion assez difficile
à maîtriser complètement...



Les exceptions ? C'est pourtant relativement simple (enfin, ça le
devient au bout de quelques années !-). Je devine que tu n'a jamais
utilisé d'autre langage supportant ce mécanisme.

Le principe général: en cas de condition imprévue, ou ingérable à ce
niveau là, ton code "lève" (raise) une exception (nb : en soi, une
exception est juste un objet, de préférence une instance de la classe
Exception ou d'une de ses sous-classes). Cela termine immédiatement et
sans autre forme de procès l'exécution de la fonction (de la méthode, du
script, bref du bout de code) en cours. Que se passe t'il à partir de
là? L'exception va remonter la pile des appels jusqu'à trouver un
gestionnaire d'exception (bloc try/except ou try/finally) correspondant
à son type. Si aucun gestionnaire n'a été trouvé, l'interpréteur Python
lui-même gère les exceptions qui remontent jusqu'à lui en affichant le
'traceback' (c'est à dire la pile des appels traversés depuis la
fonction ayant levé l'exception) et l'exception elle-même (c'est à dire
sa classe et le message d'erreur s'il y en a un).

Bref, vu de ce côté là, c'est simple: si tu tombe sur un problème que tu
ne peux pas ou ne veux pas résoudre à ce niveau, tu lèves une exception,
et tu ne te soucie pas de ce qu'elle devient.

De l'autre côté, il y a la gestion des exceptions. Un gestionnaire
d'exception est soit un bloc try/except, soit un bloc try/finally (soit
une combinaison des deux).

On va commencer par le plus commun: le bloc try/except. La syntaxe est:

try:
un_bloc_de_code
except UneClasseException:
code_pour_gerer_ce_type_d_exception
except UneAutreClasseException:
code_qui_va_bien
(etc...)
else:
code_seulement_si_pas_exception
on_reprend_le_cours_normal

Si le code un_bloc_de_code (nb: il peut y avoir plusieurs lignes de code
à ce niveau, avec tout ce qu'on veut dedans, c'est bien pour ça que je
l'ai appelé un bloc de code, pas "une_ligne_de_code") lève une
exception, le type (la classe) de cette exception va être comparée à
celles précisées par les instructions "except", *dans l'ordre de ces
instructions* (j'ai une bonne raison d'insister sur ce point...). Si
donc l'exception est une instance de la classe précisée *ou d'une
sous-classe de la classe précisée*, le code du 'bloc' except est
exécuté. Sinon, on passe au 'except' suivant (s'il y en a un), etc
jusqu'à trouver un cas qui corresponde. Si rien ne correspond,
l'exception se "propage" au code appelant (bref, c'est comme s'il n'y
avait pas eu de gestionnaire d'exception).

Le bloc try/except ne "protege" bien sûr que le code placé entre le try
et le except, et à condition qu'il y ait une clause except correspondant
au type de l'exception levée.

L'ordre des clauses except est important. Par exemple, KeyError (qui est
levée si tu essaie d'accéder à une clé inexistante dans un dict) est une
sous-classe de LookupError, qui est une sous-classe de StandardError,
qui est une sous-classe de Exception. Une clause "except StandardError"
attrapera donc non seulement les exceptions de la classe StandardError,
mais aussi celles de toutes les classes filles de StandardError (dont,
entre autres, KeyError). Les clauses except étant évaluée dans l'ordre
où elles sont déclarées, s'il y a une clause "except StandardError"
*avant* la clause "except KeyError", le gestionnaire dee dernière ne
sera jamais exécuté puisque c'est celui de la clause "except
StandardError" qui le sera:

# mauvais:
map = {"un" : 1, "trois": 3}
try:
print map["deux"] # leve une KeyError
except StandardError:
print "c'est moi qui prend la main"
except KeyError:
print "putain, l'autre con y passe toujours avant moi :("

# bon :
map = {"un" : 1, "trois": 3}
try:
print map["deux"] # leve une KeyError
except KeyError:
print "Ya pas de 'deux' dans map"
except StandardError:
print "Tiens, un problème pas prévu..."


Quelques autres trucs à savoir:

- comment examiner/manipuler/etc l'exception elle-même:
Simple: il suffit de faire suivre la clause except d'une virgule et d'un
identifiant. On pourra accéder à l'objet exception *dans le gestionnaire
correspondant* via cet identifiant:

map = {"un" : 1, "trois": 3}
try:
print map["deux"] # leve une KeyError
except KeyError, exc:
print "Ya pas de 'deux' dans map"
print "le type d'exception est : %s" % type(exc)
print "quelques infos sur exc : %s" % "n".join(dir(exc))

- comment attraper plusieurs types d'exception dans une même clause:
Simple aussi: "except" peut être suivi soit d'une classe, soit d'un
tuple de classes:

liste = range(2)
map = {"un" : 1, "trois": 3}
try:
liste[4] == map['quatre']
except (KeyError, IndexError), e:
if issinstance(e, KeyError):
print "félicitations, c'est une KeyError")
elif issintance(e, IndexError):
print "félicitations, c'est une IndexError")
else:
print "si tu me vois, c'est que Python est buggé"
raise # relance l'exception... si quelqu'un d'autre veut la gérer...

Ca va jusque là ? Bon, on continue: les bloc try/finally. Là on ne se
soucie pas du type d'exception ni rien, tout ce qu'on veut c'est qu'un
certain bout de code soit exécuté *quoi qu'il advienne* :

try:
une_ligne_qui_se_passe_bien
une_ligne_qui_peut_lever_une_exception
une_ligne_qui_ne_sera_exécutée_que_si_la_précédente_a_ete_gentille
finally:
une_ligne_qui_sera_executée_de_toutes_façons

Ce mécanisme sert généralement à libérer une ressource (fermer un
fichier ou une connection etc).

NB: quand je dis que le gestionnaire suivant la clause finally est
*toujours* exécuté, ce n'est pas une figure de style:

def fun(arg):
try:
print "arg : %s" % str(arg)
if str(arg) == "raise":
raise ValueError("arg == raise")
return "arg != raise"
finally:
print "finally"

fun("toto")
fun("raise")


En général, quand on utilise un try/finally, c'est en combinaison avec
un bloc try/except:

def fun2(arg):
try:
try:
print "arg : %s" % str(arg)
if str(arg) == "raise":
raise ValueError("arg == raise")
return "arg != raise"
except ValueError, e:
print "attrapé '%s'" % e
raise # relance l'exception
finally:
print "finally"

fun2('toto')
fun2('raise')

après relecture:
je ne sais pas si c'est très clair :(
En tous cas, c'est plus simple à utiliser qu'à expliquer.
Bon, si tu arrive à tirer quelque chose de ce post, tu a gagné le droit
de le corriger/reformuler/amender/améliorer, et de mettre le résultat
sur le wiki:
http://wikipython.flibuste.net/moin.py/Les_20exceptions

HTH
Bruno



Avatar
Bruno Desthuilliers
(snip)

Un principe que j'adopte souvent c'est de ne rien catcher au début,
et d'ajouter les catchs d'exception au fur et à mesure qu'elles se
produisent, mais je ne catche que celles là et surtout je gère l'exception.


<AOL> !-)

(nb: pour NonSenz : catcher -> attraper une exception grâce à un
try/except [en Java et C++, c'est 'try/catch')]

(snip)
Mais surtout ne jamais catcher une exception par 'except:', il faut
toujours y associer une classe,


La plus spécifique possible... un 'except Exception:' ne vaut guère
mieux qu'un 'except:'

sinon une erreur de syntaxe peut
complètement passée inaperçue et là tu peux chercher des heures...


Je témoigne - et quand j'ai compris pourquoi je venais de perdre des
heures, j'ai *maudit* l'auteur du code en question.

(snip)

Autre chose importante, quand tu crée tes propres classes, crée aussi
tes classes d'exception, avec une hierarchie exemple:

class TaClasse:
def .... etc

class ExceptionTaClasse(Exception): # Classe générique de l'exception
pass

class OverflowTaClasse(ExceptionTaClasse): # Classe spécialisée d'exception
...

class MissingValueTaClasse(ExceptionTaClasse): # Classe spécialisée
d'exception
....


Oui, enfin, si ça a un sens. La multiplication des classes d'exception
n'aide pas forcément. En général, je commence par voir quelle classe
d'exception 'standard' pourrait convenir. Et si je dois en créer une
nouvelle, j'essaie aussi de dériver une sous-classe standard plutôt
qu'Exception.

Mes deux centimes...

Avatar
R12y
On Wed, 02 Nov 2005 03:09:55 +0100, Bruno Desthuilliers wrote:

Mais surtout ne jamais catcher une exception par 'except:', il faut
toujours y associer une classe,


La plus spécifique possible... un 'except Exception:' ne vaut guère
mieux qu'un 'except:'


Je viens de rencontrer ce dilemme:
Pour une création de fichier, je dois gérer deux exceptions. Soit le
fichier existe déjà, soit je n'ai pas les droits necessaires pour créer
dans le répertoire. Dans ce cas là, qui est quand même un cas relativement
répandu, mentionner l'exception est quand même avantageux... non?

--
Rakotomandimby Mihamina,
http://aspo.rktmb.org/activites/infogerance
Serveurs* sous Debian, Fedora...
(*) Serveurs!?: http://fr.search.yahoo.com/search?p=serveurs+dedies


Avatar
bruno at modulix
R12y wrote:
On Wed, 02 Nov 2005 03:09:55 +0100, Bruno Desthuilliers wrote:


Mais surtout ne jamais catcher une exception par 'except:', il faut
toujours y associer une classe,





La plus spécifique possible... un 'except Exception:' ne vaut guère
mieux qu'un 'except:'



Je viens de rencontrer ce dilemme:
Pour une création de fichier, je dois gérer deux exceptions. Soit le
fichier existe déjà, soit je n'ai pas les droits necessaires pour créer
dans le répertoire. Dans ce cas là, qui est quand même un cas relativement
répandu, mentionner l'exception est quand même avantageux... non?


Je ne suis pas sûr qu'on se comprenne, là. Ce que j'essaye de dire,
c'est que spécifier la classe 'Exception' (et non une sous-classe plus
spécifique) dans une clause except revient pratiquement au même que ne
pas spécifier de classe du tout: dans les deux cas, on ratisse beaucoup
trop large.


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"



Avatar
R12y
On Wed, 02 Nov 2005 10:25:10 +0100, bruno at modulix wrote:

spécifier la classe 'Exception'


Effectivement, j'ai mal compris. Essentiellement dû à mon "incompétence",
je te rassure.

--
Rakotomandimby Mihamina,
http://aspo.rktmb.org/activites/infogerance
Serveurs* sous Debian, Fedora...
(*) Serveurs!?: http://fr.search.yahoo.com/search?p=serveurs+dedies

Avatar
remi_inconnu
[Snip]

class TaClasse:
def .... etc

class ExceptionTaClasse(Exception): # Classe générique de l'excepti on
pass

class OverflowTaClasse(ExceptionTaClasse): # Classe spécialisée d'e xception
...

class MissingValueTaClasse(ExceptionTaClasse): # Classe spécialisée
d'exception
....


Oui, enfin, si ça a un sens. La multiplication des classes d'exception
n'aide pas forcément. En général, je commence par voir quelle classe
d'exception 'standard' pourrait convenir. Et si je dois en créer une
nouvelle, j'essaie aussi de dériver une sous-classe standard plutôt
qu'Exception.


Pour un module que tu veux réutiliser dans une plus grosse
application, c'est préférable de typer et de hiérarchiser les
exceptions, c'est d'ailleurs le cas de ce que l'on trouve dans les
bonnes librairies Python. Pour une petite appli, je suis d'accord avec
toi, cela ne se justifie pas toujours...



Mes deux centimes...



Avatar
bruno at modulix
wrote:
[Snip]

class TaClasse:
def .... etc

class ExceptionTaClasse(Exception): # Classe générique de l'exception
pass

class OverflowTaClasse(ExceptionTaClasse): # Classe spécialisée d'exception
...

class MissingValueTaClasse(ExceptionTaClasse): # Classe spécialisée
d'exception
....


Oui, enfin, si ça a un sens. La multiplication des classes d'exception
n'aide pas forcément. En général, je commence par voir quelle classe
d'exception 'standard' pourrait convenir. Et si je dois en créer une
nouvelle, j'essaie aussi de dériver une sous-classe standard plutôt
qu'Exception.



Pour un module que tu veux réutiliser dans une plus grosse
application, c'est préférable de typer et de hiérarchiser les
exceptions,


Je n'ai pas parlé de ne pas typer ni hiérachiser les exceptions, juste
de commencer par utiliser les exceptions standard quand elles sont
appropriées, et ne créer ses propres classes d'exception que quand ça à
un sens. Si mon module défini une classe dict-like, je ne vais pas a
priori définir aussi une exception MonModuleKeyError - la classe
KeyError suffit.

Et si cela a un sens de créer une classe d'exception spécifique, je ne
vais pas forcément non plus créer une classe de base MonModuleException
et dériver de cette classe s'il me semble que sémantiquement ma classe
d'exception est un sous-type d'une classe d'exception standard.

c'est d'ailleurs le cas de ce que l'on trouve dans les
bonnes librairies Python.


s/les/certaines/ ...

Pour une petite appli, je suis d'accord avec
toi, cela ne se justifie pas toujours...


Que ce soit une appli ou une bibliothèque n'est pas le problème AMAH, il
s'agit surtout de ne pas réinventer la roue. Si je reprend l'exemple du
module définissant un dict-like, le but de la manoeuvre est que cette
classe soit autant que possible un sous-type de dict. Si je défini une
classe d'exception spécifique qui ne soit pas une sous-classe de
KeyError, je risque de casser pas mal de code prévu pour utiliser un
dict (et qui donc s'attend à de KeyError, pas à des MonModuleError).

Je me doute bien que tu ne ferais pas cette erreur, mais en est-il de
même pour un débutant suivant ton conseil avec un peu trop de zèle ?


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"



1 2