web-dev-qa-db-fra.com

Comment gérer AssertionError dans Python et savoir sur quelle ligne ou instruction il s'est produit?)

Je veux gérer AssertionErrors à la fois pour masquer des parties inutiles de la trace de pile à l'utilisateur et pour imprimer un message expliquant pourquoi l'erreur s'est produite et ce que l'utilisateur doit faire à ce sujet.

Existe-t-il un moyen de savoir sur quelle ligne ou instruction le assert a échoué dans le bloc except?

try:
    assert True
    assert 7 == 7
    assert 1 == 2
    # many more statements like this
except AssertionError:
    print 'Houston, we have a problem.'
    print
    print 'An error occurred on line ???? in statement ???'
    exit(1)

Je ne veux pas avoir à ajouter ceci à chaque déclaration d'assertion:

assert 7 == 7, "7 == 7"

parce qu'il répète l'information.

49
devtk

Utilisez le module traceback :

import sys
import traceback

try:
    assert True
    assert 7 == 7
    assert 1 == 2
    # many more statements like this
except AssertionError:
    _, _, tb = sys.exc_info()
    traceback.print_tb(tb) # Fixed format
    tb_info = traceback.extract_tb(tb)
    filename, line, func, text = tb_info[-1]

    print('An error occurred on line {} in statement {}'.format(line, text))
    exit(1)
62
phihag

Le module traceback et sys.exc_info sont excessifs pour retrouver la source d'une exception. C'est tout dans le traçage par défaut. Donc au lieu d'appeler exit (1), relancez simplement:

try:
    assert "birthday cake" == "ice cream cake", "Should've asked for pie"
except AssertionError:
    print 'Houston, we have a problem.'
    raise

Ce qui donne la sortie suivante qui inclut la déclaration incriminée et le numéro de ligne:

Houston, we have a problem.
Traceback (most recent call last):
  File "/tmp/poop.py", line 2, in <module>
    assert "birthday cake" == "ice cream cake", "Should've asked for pie"
AssertionError: Should've asked for pie

De la même manière, le module de journalisation facilite la journalisation d'une trace pour toute exception (y compris celles qui sont interceptées et qui ne sont jamais ré-levées):

import logging

try:
    assert False == True 
except AssertionError:
    logging.error("Nothing is real but I can't quit...", exc_info=True)
18
notpeter