Récemment, je me demandais comment rendre l'affichage des exceptions de module en Python plus facile à comprendre, mais j'ai trouvé la meilleure méthode, alors je l'ai résumée. Tout d'abord, passons en revue la méthode générale de définition des exceptions de module.
Comme situation concrète, considérons la situation d'écriture du module urllib83 constitué de la fonction ʻurllib83.urlopen () `en Python 3.3. urllib83 signifie le 83ème module urllib, mais je suis désolé si un module standard avec le même nom apparaît dans le futur.
En dehors de cela, supposons que ce module se compose des trois fichiers suivants.
urllib83/__init__.py
ftp.py
http.py
Si vous écrivez ʻurllib83.urlopen () autant que vous le pouvez, cela devrait ressembler à ceci.
__init__.py
from .ftp import ftpopen
from .http import httpopen
def urlopen(url):
if url.startswith("ftp://"):
return ftpopen(url)
else:
return httpopen(url)
Ensuite, supposons que ce module a des classes d'exception ʻurllib83.FTPError et ʻurllib83.HTTPError
, qui héritent toutes deux de la classe d'exception de base ʻurllib83.Urllib83Error. Si vous implémentez ces trois classes d'exception docilement, dans ʻurllib83 / __ init __. Py
,
urllib83/__init__.py
class Urllib83Error(Exception):
pass
class FTPError(Urllib83Error):
pass
class HTTPError(Urllib83Error):
pass
Je pense que ce sera défini comme, mais il y a un problème avec cette méthode.
ʻUrllib83.FTPError est naturellement déclenché dans ʻurllib83 / ftp.py
, donc ftp.py
lèvera FTPError
,
urllib83/ftp.py
from . import FTPError
def ftpopen(url):
...
raise FTPError
Il est utilisé en important comme, mais comme mentionné ci-dessus, __init __. Py
importe ftpopen ()
from ftp.py
.
À ce rythme, «__init __. Py» et «ftp.py» s'importeront mutuellement, causant le problème de l'importation circulaire.
Donc, en général, pour éviter ce problème, ajoutez un fichier appelé ʻurllib83 / errors.py` et faites-le comme suit.
urllib83/errors.py
class Urllib83Error(Exception):
pass
class FTPError(Urllib83Error):
pass
class HTTPError(Urllib83Error):
pass
Chaque fichier autre que ʻerrors.py`
__init__.py
from .errors import Urllib83Error, FTPError, HTTPError
__all__ = ['Urllib83Error', 'FTPError', 'HTTPError']
Importez la classe d'exceptions requise comme dans. (Remarque:__all__
A besoin de la ligne__init__.py
seulement. )
__init__.py
Importe également la classe d'exception, donc le côté utilisant le module urllib83 également
client.py
from urllib83 import urlopen, Urllib83Error
try:
urlopen(url)
except Urllib83Error:
pass
Vous pouvez utiliser des exceptions de module comme celle-ci. Il n'y a rien de mal à cela.
##Qu'est-ce qui ne va pas?##
Ce qui m'intéressait, c'est que le côté utilisant le module urllib83 a essayé...Sans utiliser l'instruction excepturllib83.urlopen()
Quand vous appelez.
urllib83.FTPError
Lorsque cela se produit, le suivi s'affiche comme indiqué ci-dessous.
python
>>> import urllib83
>>> urllib83.urlopen("ftp://")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./urllib83/__init__.py", line 10, in urlopen
return ftpopen(url)
File "./urllib83/ftp.py", line 4, in ftpopen
raise FTPError
urllib83.errors.FTPError
>>>
Dans la dernière ligneurllib83.FTPError
ne pas,urllib83.errors.FTPError
Est affiché.
C'est un problème,urllib83.FTPError
Je suis d'avis qu'il devrait être affiché.
Cependant, le point de vue général des gens de Pythonista est que "je n'ai aucune idée du problème dans cet affichage." La raison est
La documentation du module urllib83
urllib83.FTPError
Se produira, et l'utilisateur dira dans la clause except,except urllib83.FTPError:
Vous pouvez compléter l'exception qui s'est produite par écrit. Le problème n'existe nulle part car il fonctionne selon les spécifications décrites dans la documentation
est ce qu'ils ont dit. D'un autre côté, mon contre-argument à cela est
L'utilisateur du module urllib83
urllib83.errors.FTPError
A été mentionné dans la documentation du module urllib83 lorsque j'ai effectivement rencontré l'indicationurllib83.FTPError
N'est-ce pas trop cher de le savoir? Depuis le début,urllib83.FTPError
Est plus facile à comprendre et convivial, vous devriez donc faire quelque chose à ce sujet.
C'est.
##Solution##
urllib83.FTPError
J'ai essayé différentes manières de l'afficher, mais à la finerrors.py
Classe d'exception avec
errors.py
_SAVED_NAME = __name__
__name__ = __package__
# __name__ = "urllib83" # Cliquez ici pour Python 3.2
class Urllib83Error(Exception):
pass
class FTPError(Urllib83Error):
pass
class HTTPError(Urllib83Error):
pass
__name__ = _SAVED_NAME
Je suis arrivé à la conclusion qu'il semble préférable de le définir comme.
Le point est__name__
Réécrivez temporairement le contenu de l'attribut et restaurez-le lorsque la classe d'exception a été définie.
Lorsqu'une exception se produit, ce qui suit s'affiche.
python
>>> import urllib83
>>> urllib83.urlopen("ftp://")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./urllib83/__init__.py", line 10, in urlopen
return ftpopen(url)
File "./urllib83/ftp.py", line 4, in ftpopen
raise FTPError
urllib83.FTPError
>>>
Correctementurllib83.FTPError
Est affiché.
__name__
La réécriture des attributs n'est pas courante, et si vous écrivez du code complexe,urllib83/__init__.py
Il peut y avoir une différence par rapport à la définition dans, donc__name__
Nous vous recommandons vivement d'éviter autant que possible les traitements compliqués lors de la réécriture des attributs.
puis,__name__
N'oubliez pas d'annuler les attributs.
##finalement## Jusqu'à présent, nous n'avons trouvé aucun problème avec cette méthode, mais si vous remarquez des problèmes, veuillez nous en informer dans les commentaires. Personnellement, n'y a-t-il pas quelque chose qui cloche dans l'environnement de développement intégré? Je suis particulièrement inquiet à ce sujet.
Recommended Posts