web-dev-qa-db-fra.com

Imprimer un message d'erreur sans imprimer de trace et fermer le programme lorsqu'une condition n'est pas remplie

J'ai déjà vu des questions similaires à celle-ci, mais aucune d'entre elles ne traite vraiment du rétrolien. Si j'ai un cours comme celui-ci

class Stop_if_no_then():
    def __init__(self, value one, operator, value_two, then, line_or_label, line_number):
        self._firstvalue = value_one
        self._secondvalue = value_two
        self._operator = operator
        self._gohere = line_or_label
        self._then = then
        self._line_number = line_number

    def execute(self, OtherClass):
        "code comparing the first two values and making changes etc"

Ce que je veux que ma méthode d’exécution puisse faire, c’est si self._then n’est pas égal à la chaîne "THEN" (dans allcaps), alors je veux qu’il déclenche un message d’erreur personnalisé et mette fin au programme entier sans afficher de trace. .

Si l'erreur est rencontrée, la seule chose à imprimer devrait ressembler à quelque chose (j'utilise 3 par exemple, le formatage n'est pas un problème) ceci.

`Syntax Error (Line 3): No -THEN- present in the statement.`

Je ne suis pas très pointilleux sur le fait qu'il s'agisse d'un objet de classe exception, il n'y a donc aucun problème à cet aspect. Depuis que je vais utiliser cela dans une boucle while, simple si, Elif se contente de répéter le message encore et encore (car évidemment je ne ferme pas la boucle). J'ai vu sys.exit () mais cela affiche également un bloc de texte rouge géant, à moins que je ne l'utilise pas correctement. Je ne veux pas attraper l'exception dans ma boucle car il y a d'autres classes dans le même module dans lesquelles je dois implémenter quelque chose comme ceci.

13
user2560035

Vous pouvez utiliser un try: puis un except Exception as inst: Cela vous donnera votre message d'erreur dans une variable nommée inst et vous pourrez imprimer les arguments de l'erreur avec inst.args. Essayez de l’imprimer et de voir ce qui se passe, et l’un des éléments de inst.args est celui que vous recherchez.

EDIT Voici un exemple que j'ai essayé avec pythons IDLE:

>>> try:
    open("epik.sjj")
except Exception as inst:
    d = inst


>>> d
FileNotFoundError(2, 'No such file or directory')
>>> d.args
(2, 'No such file or directory')
>>> d.args[1]
'No such file or directory'
>>> 

EDIT 2: comme pour fermer le programme, vous pouvez toujours raise et erreur ou vous pouvez utiliser sys.exit()

8
The-IT

Vous pouvez désactiver le traçage en limitant sa profondeur.

Python 2.x

import sys
sys.tracebacklimit = 0

Python 3.x

Dans Python 3.5.2 et 3.6.1, définir tracebacklimit sur 0 ne semble pas avoir l'effet escompté. Ceci est un connu bug . Notez que -1 ne fonctionne pas non plus. Le réglage sur None semble toutefois fonctionner, du moins pour le moment.

>>> import sys

>>> sys.tracebacklimit = 0
>>> raise Exception
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception

>>> sys.tracebacklimit = -1
>>> raise Exception
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception

>>> sys.tracebacklimit = None
>>> raise Exception
Exception

Néanmoins, pour le meilleur ou pour le pire, si plusieurs exceptions sont soulevées, elles peuvent toutes être imprimées. Par exemple:

socket.gaierror: [Errno -2] Name or service not known

During handling of the above exception, another exception occurred:

urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>
46
Marco Costa

Le moyen le plus propre que je connaisse est d'utiliser sys.excepthook.

Vous implémentez une fonction à trois arguments qui accepte type, value et traceback et fait ce que vous voulez (par exemple, n'imprime que la valeur) et affectez cette fonction à sys.excepthook.

Voici un exemple:

import sys

def excepthook(type, value, traceback):
    print(value)

sys.excepthook = excepthook

raise ValueError('hello')

Ceci est disponible dans Python 2 et Python 3.

4
Mark Veltzer

Si vous voulez vous débarrasser de toute trace pour les exceptions douanières et avoir un numéro de ligne, Vous pouvez faire cette astuce

Python 3

import sys
import inspect

class NoTraceBackWithLineNumber(Exception):
    def __init__(self, msg):
        try:
            ln = sys.exc_info()[-1].tb_lineno
        except AttributeError:
            ln = inspect.currentframe().f_back.f_lineno
        self.args = "{0.__name__} (line {1}): {2}".format(type(self), ln, msg),
        sys.exit(self)

class MyNewError(NoTraceBackWithLineNumber):
    pass

raise MyNewError("Now TraceBack Is Gone")

Donnera cette sortie et rendra le mot clé raise inutile

MyNewError (line 16): Now TraceBack Is Gone
2
creuilcreuil

En général, si vous voulez intercepter une exception à l'exception de SystemExit et quitter avec le message de l'exception sans traceback, définissez votre fonction main comme ci-dessous:

>>> import sys

>>> def main():
...     try:
...         # Run your program from here.
...         raise RandomException  # For testing
...     except (Exception, KeyboardInterrupt) as exc:
...         sys.exit(exc)
... 
>>> main()
name 'RandomException' is not defined

$ echo $?
1

Notez que dans le cas où plusieurs exceptions sont levées, un seul message est imprimé.

Cette réponse est destinée à améliorer le one by The-IT .

2
A-B-B