TL;DR : Il est préférable de lever une exception "normale" et d'utiliser la fonction SystemExit
o sys.exit
uniquement aux niveaux supérieurs d'un script.
Je suis sur python 2.7 et Linux, j'ai un code simple, j'ai besoin d'une suggestion si je peux remplacer sys.exit(1) par raise SystemExit. Je pourrais remplacer sys.exit(1) par raise SystemExit .
\==Code réel===
def main():
try:
create_logdir()
create_dataset()
unittest.main()
except Exception as e:
logging.exception(e)
sys.exit(EXIT_STATUS_ERROR)
if __name__ == '__main__': main()
\==Changement de code===
def main():
try:
create_logdir()
create_dataset()
unittest.main()
except Exception as e:
logging.exception(e)
raise SystemExit
if __name__ == '__main__':
main()
Personnellement, je suis contre les deux. Le modèle que je préfère est le suivant ceci :
def main(argv):
try:
...
except Exception as e:
logging.exception(e)
return 1
if __name__ == '__main__':
sys.exit(main(sys.argv))
Remarquez que main() redevient une fonction normale avec des fonctions normales normaux.
En outre, la plupart d'entre nous éviteraient l'expression "sauf exception" et laisseraient simplement un niveau supérieur à "sauf bubb". niveau supérieur : de cette façon, vous obtenez une trace de la pile pour le débogage. débogage. Je suis d'accord pour dire que cela empêche la journalisation de l'exception et que cela rend la sortie de la console plus laide. la sortie console plus laide, mais je pense que c'est une victoire. Et si vous faire vouloir enregistrer l'exception, il y a toujours ceci :
essayer : ... sauf Exception comme e : logging.exception(e) raise
de réciter l'exception dans le journal et de la laisser ressortir normalement. normalement.
Le problème avec le modèle "except Exception" est qu'il attrape et cache tous et pas seulement l'ensemble restreint d'exceptions spécifiques que vous comprenez.
Enfin, il est mal vu d'élever une classe d'exception. En python 3, je crois que c'est en fait interdit, et donc non portable. de toute façon. Mais même en Python 2, il est préférable de fournir une instance d'Exception et non la classe :
raise SystemExit(1)
- Toutes les fonctions dans le bloc d'essai ont une exception qui est levée à l'aide de raise.
Exemple pour create_logdir() voici la définition de la fonction
def create_logdir() :
essayer : os.makedirs(LOG_DIR) except OSError as e : sys.stderr.write("Failed to create log directory...Exiting ! !!") raise print "fichier journal : " + corrupt_log return True
def main() : try : create_logdir() except Exception as e : logging.exception(e) raise SystemExit
(a) Si create_logdir() échoue, nous obtiendrons le message d'erreur suivant cela convient-il ou dois-je améliorer ce code ?
Failed to create log directory...Exiting !!!ERROR:Root :[Errno 17] File existe : '/var/log/dummy'
Traceback (dernier appel le plus récent) : Fichier "corrupt_test.py", ligne 245, in main create_logdir() Fichier "corrupt_test.py", ligne 53, in create_logdir os.makedirs(LOG_DIR) Fichier "/usr/local/lib/python2.7/os.py", ligne 157, in makedirs OSError : [Errno 17] Le fichier existe : '/var/log/dummy'
Je préfère l'approche de la bulle, peut-être avec un journal ou un avertissement. comme vous l'avez fait, par exemple :
logging.exception("create_logdir failed : makedirs(%r) : %s" % (LOG_DIR, e)) raise
(Il ne faut pas non plus que ce message enregistre plus de contexte : le contexte est très utile pour déboguer les problèmes). très utile lors du débogage des problèmes).
Pour de très petits scripts sys.stderr.write est correct, mais en général, toutes les fonctions qui ont un impact sur le fonctionnement de l'ordinateur sont des fonctions qui ne peuvent pas être utilisées. fonctions qui se sont avérées généralement utiles pourraient migrer. dans une bibliothèque afin d'être réutilisées ; considérez que stderr n'est pas n'est pas toujours l'endroit pour les messages ; au lieu de cela, lisez pour le module de journalisation avec error() ou wanr() ou exception() selon le cas. Il y a plus de de configurer l'emplacement de la sortie sans l'intégrer à votre fonction interne. dans vos fonctions internes.
- Puis-je me contenter de lever, au lieu de SystemExit ou sys.exit(1) . Cette me semble erroné
def main() :
essayer : create_logdir() except Exception as e logging.exception(e) raise
C'est ce que je ferais moi-même.
Réfléchissez : l'exception a-t-elle été "traitée", c'est-à-dire la situation a-t-elle été a-t-elle été traitée comme prévu ? Si ce n'est pas le cas, laissez l'exception l'exception afin que l'utilisateur sache que quelque chose s'est passé. pas compris par le programme a eu lieu.
Enfin, il est généralement déconseillé d'utiliser SystemExit ou sys.exit() à l'intérieur de autre chose que la fonction main() la plus extérieure. Et je m'y oppose même là ; la fonction principale, si elle est bien écrite, peut souvent être appelée d'un autre endroit, ce qui en fait effectivement une fonction de bibliothèque (elle a été réutilisée). Une telle fonction ne devrait pas unilatéralement interrompre le programme. Quelle impolitesse ! Au lieu de cela, laissez l'exception s'exprimer : peut-être que la fonction appelant de main() l'attend et peut gérer et peut la gérer. En abandonnant et en ne levant pas le problème, vous avez privé l'appelant de la possibilité de faire quelque chose d'approprié, même s'il n'est pas en mesure de le faire. la possibilité de faire quelque chose d'approprié, même si vous-même (c'est à dire "main") ne savez pas qu'il y a un problème. (c'est-à-dire "main") ne connaît pas suffisamment le contexte pour gérer l'exception.
Je suis donc moi-même en faveur d'une "augmentation". Et seulement parce que vous voulez enregistrer l l'erreur. Si vous ne vouliez pas enregistrer l'exception, vous pourriez éviter l'utilisation de la fonction try/except entièrement et avoir un code plus simple : laisser l'appelant se préoccuper des exceptions non gérées !