En python, chaque fois que j'utilise l'assertion et qu'elle est déclenchée, je n'ai qu'une information laide:
AssertionError: 2 != 3
Que dois-je faire pour générer automatiquement un message expliquant la cause de l'erreur, en analysant l'AST de l'argument condition?
Exemple: Donc
assert 2 == 3
causes:
AssertionError
3 Réponses :
Si les dépendances posent problème, vous pouvez le faire facilement vous-même. c'est-à-dire:
def assert_eq(x, y): if x != y: print('error: {} != {}'.format(x, y)) assert x == y
Un moyen simple d'atteindre votre objectif serait d'utiliser une fonction wrapper qui prend la condition affirmée comme un paramètre de chaîne, afin que vous puissiez l'évaluer
et affirmer
le résultat, tout en interceptant AssertionError
dans un bloc try
, afin que vous puissiez re-lever l'exception avec la chaîne donnée sous forme de message:
AssertionError: 2 == 3
pour que:
my_assert('2 == 3')
soulève:
def my_assert(condition): try: assert eval(condition) except AssertionError as e: e.args = condition, raise
Besoin d'un peu plus de détails pour montrer comment cela fonctionnerait avec x et y, je pense. Cette fonction ne connaîtra pas ces variables si elle est appelée avec "x == y" `
Il n'en a pas besoin. La condition est transmise sous forme de chaîne et est directement eval
, donc c'est au compilateur Python de l'interpréter. Ce que cette réponse ne fait pas est de déclencher l'erreur avec une condition opposée à celle donnée (donc 2 == 3
est signalé comme 2! = 3
), ce qui est ce que le PO déclare qu'il / elle veut mais je ne pense pas que ce soit nécessaire à son objectif.
eval
a des implications sur la sécurité. Considérez plutôt ast.literal_eval
. Voir stackoverflow.com/a/15197698/2958070
@Ben À moins que toutes vos assertions ne concernent des constantes, ast.literal_eval
ne convient pas à cette fin car il y a des chances que des noms de variables soient impliqués dans la condition donnée, ce que ast.literal_eval
a gagné ' t être en mesure de résoudre. Les affirmations sont pour le développement de toute façon et le code de production devrait être dépouillé d'assertions, donc la sécurité ne devrait pas être un problème en premier lieu.
@blhsing Je n'avais pas réalisé à propos des variables vissées avec ast.literal_eval
, merci.
Puisque AssertionError
est une classe, vous pouvez dériver la vôtre qui fait ce que vous voulez. La partie la plus délicate est de le connecter pour que l'interpréteur l'utilise avec l'instruction assert
.
Voici quelque chose qui semble fonctionner, mais je ne sais pas si ce sera le cas lorsqu'il est utilisé avec le notebook jupyter.
import builtins import traceback class MyAssertionError(builtins.AssertionError): def __init__(self, *args): super(MyAssertionError, self).__init__(*args) raw_tb = traceback.extract_stack() entries = traceback.format_list(raw_tb) # Remove the last two entries for the call to extract_stack(). Each # entry consists of single string with consisting of two lines, the # script file path then the line of source code making the call to this # function. del entries[-2:] self.lines = '\n'.join(entries) def __str__(self): return super(MyAssertionError, self).__str__() + '\n' + self.lines builtins.AssertionError = MyAssertionError # Replace builtin. if __name__ == '__main__': assert 2 == 3
Utilisez juste pytest?
Je veux, mais je ne suis pas sûr que pytest supportera un jour jupyter notebook: - <
Si le support de jupyter est une limitation, vous devriez vraiment l'avoir dans la question .