7
votes

Avertissements du point de vue de l'appelant (Aka Python - équivalent de la carpe de Perl)?

Version courte:

Il y a une façon de réaliser dans Python le même effet obtenu par carpe :: carpe utilitaire?

Version longue (pour ceux qui inconnus avec carpe :: carpe ):

Supposons que nous mettions implémenter une fonction d'API de bibliothèque (c'est-à-dire qu'il est censé être censé être utilisé par d'autres programmeurs dans leur code), disons spam et supposons que spam inclut un code pour vérifier la validité des arguments transmis . Bien entendu, ce code est censé soulever une exception si un problème de ces arguments est détecté. Disons que nous voulons rendre le message d'erreur associé et la traçabilité aussi utile que possible à quelqu'un de débogage du code client.

Idéalement, la dernière ligne de la traçabilité produite par cette exception soulevée doit identifier le "code fautif ", à savoir la ligne dans le code de la client spam a été appelé avec des arguments non valides.

Malheureusement, ce n'est pas ce qui se passerait, du moins par Par défaut, en utilisant Python. Au lieu de cela, la dernière ligne de la trace de traçage se référera à quelque part dans les internes du code de la bibliothèque, où l'exception était en réalité élever d, qui serait assez obscure au public prévu de cette Traceback particulier.

Exemple: xxx

Lorsque nous exécutons client.py , nous obtenons: xxx

alors que ce que nous voulons se rapprocher de: xxx

... avec le code fautif ( x = SPAM (FALSE, FALSE) ) En tant que dernière ligne de la traçabilité.

Ce dont nous avons besoin est un moyen de signaler l'erreur "du point de vue de l'appelant" (qui est ce que Carp :: carpe Permet à Perl).

Edit: Juste pour être clair, cette question ne concerne pas Lbyl vs EAFP, ni sur les conditions préalables ou la programmation par contrat. Je suis désolé si j'ai donné cette mauvaise impression. Cette question concerne comment produire une trace de trace à partir de quelques niveaux (un, deux) sur la pile d'appels.

EDIT2: Python's Traceback est un endroit évident à rechercher Un équivalent python de carpe de Perl :: carpe , mais après l'avoir étudié pendant un certain temps, je ne pouvais trouver aucun moyen de l'utiliser pour ce que je veux faire. FWIW, Perl's's's's's's's's's's's's's> Carp :: Carp permet un ajustement fin de la trame initiale pour la traçabilité en exposant la variable globale (par conséquent scopée de manière dynamique) $ carpe :: Carplevel . Fonctions de la bibliothèque non-API qui peut carpe -out, local -ormer et augmenter cette variable sur l'entrée (par exemple, local $ carpe :: Carplevel + = 1; / code>). Je ne vois rien même à distance à distance comme ce module de la traçabilité de Python. Ainsi, sauf si j'ai manqué quelque chose, toute solution qui utilise le de Python's devrait prendre une claquette assez différente ...


0 commentaires

3 Réponses :


1
votes

Vous pouvez utiliser essayer..except code> dans la fonction API de niveau supérieur ( foo code>) pour soulever une exception différente:

class FooError(Exception): pass

def foo():
    try:
        bar()
    except ZeroDivisionError:
        raise FooError()

def bar():
    baz()

def baz():
    1/0

foo()


1 commentaires

La traçabilité n'apparaîtrait toujours pas "du point de vue de l'appelant"



2
votes

Il s'agit vraiment d'une question de convention, la manipulation des exceptions à Python est conçue pour être utilisée fortement (prier le pardon plutôt que de demander la permission). Et étant donné que vous travaillez dans un espace de langue différent, vous souhaitez suivre ces conventions - c'est-à-dire / vous souhaitez vraiment laisser les développeurs savoir où se trouvait le site de l'exception. Mais si vous avez vraiment besoin de faire cela ...

à l'aide du module d'inspection fort> p>

Inspecter le module fera à peu près tout ce dont vous avez besoin pour reconstruire une belle version de la carpe, qui fonctionne sans avoir à vous soucier des décorateurs (voir ci-dessous). Selon le commentaires dans cette réponse , c'est peut-être que Cette approche va rompre sur des pythons autres que cpython p> xxx pré>

qui pour l'exemple suivant: p> xxx pré>

produit la sortie: xxx pré>

à l'aide de la traçabilité forte> p>

C'était l'approche originale proposée. EM> P> P> P> P> P > Un équivalent à la carpe pourrait également être écrit en Python en manipulant des objets de voyageur, voir la documentation dans le Module . Le principal défi pour cela s'avère être injecté de l'exception et du code d'impression de trace. Il convient de noter que le code de cette section est très fragile. P> xxx pré>

qui peut être appelé à l'aide du processus de base suivant: p>

msg at foo.pl line 6
    main::f() called at foo.pl line 10
    main::g() called at foo.pl line 13


3 commentaires

Je suis un peu familier avec le module de trace, mais je ne vois aucun moyen de l'utiliser pour ce que je veux faire. Si vous avez quelque chose de concret concret, cela vous aiderait à voir de la croquis de code de code. (Aussi, voir ma dernière modification, pour plus d'informations sur la façon dont $ carpe :: carpe résout ce problème.)


@kjo j'ai modifié ma réponse pour montrer une approche possible Utilisez le module de trace


@kjo, j'ai ajouté une deuxième solution permettant d'utiliser un python équivalent à la carpe sans aucun code de support.



1
votes

Ce que vous voulez faire est appelé fonction d'établissement conditions préalables , et il n'y a pas de support de langue à Python. Python n'est également pas aussi parfaitement piraquable que Perl (sauf si vous utilisez peut-être si vous utilisez pypy), il ne peut donc pas être ajouté d'une manière entièrement transparente.

qui étant dit, le module pycontracts semble le faire relativement en douceur en utilisant des décorateurs de fonction et des spécifications de préconformation à base de cordes. Je n'ai pas utilisé le module moi-même, mais il semble que cela puisse vous obtenir quelque chose de plus près ce que vous voulez. Voici le premier exemple donné sur sa page d'information: xxx


0 commentaires