Existe-t-il un moyen d'empêcher qu'une exception SystemExit générée par sys.exit () soit interceptée?

StackOverflow https://stackoverflow.com/questions/173278

Question

La documentation indique que l'appel de sys.exit () génère une exception SystemExit qui peut être interceptée dans les niveaux externes. J'ai une situation dans laquelle je veux sortir définitivement et sans aucun doute de l'intérieur d'un scénario de test, mais le module unittest attrape SystemExit et empêche la sortie. C’est normalement bien, mais la situation spécifique que j’essaie de gérer est celle dans laquelle notre infrastructure de test a détecté qu’elle est configurée pour pointer vers une base de données non test. Dans ce cas, je souhaite quitter et empêcher tout test supplémentaire d'être exécuté. Bien sûr, étant donné que Unittest piège la SystemExit et continue heureusement, il me contrarie.

La seule option à laquelle j'ai pensé jusqu’à présent consiste à utiliser des ctypes ou quelque chose de similaire à appeler exit (3) directement, mais cela semble être un sacré bidouillage pour quelque chose qui devrait être très simple.

Était-ce utile?

La solution

Vous pouvez appeler le os._exit () pour quitter directement, sans lever d'exception:

import os
os._exit(1)

Ceci contourne toute la logique d'arrêt python, telle que le module atexit , et ne passera pas par la logique de traitement des exceptions que vous essayez d'éviter dans cette situation. L'argument est le code de sortie qui sera renvoyé par le processus.

Autres conseils

Comme Jerub a dit, os._exit (1) est votre réponse. Mais, considérant qu’il contourne toutes les procédures de nettoyage, y compris les enfin: blocs, les fichiers fermés, etc., et devrait vraiment être évité à tout prix, puis-je présenter un rapport plus sûr? ish " façon de l'utiliser?

Si votre problème persiste si SystemExit est capturé aux niveaux extérieurs (c'est-à-dire unittest), alors sera le niveau extérieur vous-même! code dans un bloc try / except, intercepte SystemExit et appelle os._exit à cet emplacement, et uniquement à cet emplacement! Ainsi, vous pouvez appeler sys.exit normalement, n’importe où dans le code, laissez-le remonter au premier niveau, fermez gracieusement tous les fichiers et exécutez tous les nettoyages, puis puis appelez os._exit.

Vous pouvez même choisir les sorties "d'urgence". les uns. Le code ci-dessous est un exemple d'une telle approche:

import sys, os

EMERGENCY = 255  # can be any number actually

try:
    # wrap your whole code here ...
    # ... some code
    if x: sys.exit()
    # ... some more code
    if y: sys.exit(EMERGENCY)  # use only for emergency exits
    # ...
except SystemExit as e:
    if e.code != EMERGENCY:
        raise  # normal exit, let unittest catch it
    else:
        os._exit(EMERGENCY)  # try to stop *that*, sucker!
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top