versión corta:Advertencias desde la perspectiva del llamador (también conocido como Python-equivalente de la carpa de Perl)?
¿Hay manera de lograr en Python el mismo efecto que se consigue por la utilidad de Perl
Carp::carp
?
Versión larga (para los que no conocen Carp::carp
):
Supongamos que estamos llevando a cabo alguna función API de biblioteca (es decir, que está destinado a ser utilizado por otros programadores en su código), dicen spam
, y supongamos que spam
incluye algún código para verificar la validez de los argumentos que se le pasan. Por supuesto, se supone que este código genera una excepción si se detecta algún problema con estos argumentos. Digamos que queremos que el mensaje de error asociado y el rastreo sean lo más útiles posible para alguien que esté depurando algún código de cliente.
Idealmente, la última línea de la traza producida por este levantaron excepción debe señalar el "código erróneo", es decir, la línea en el código cliente donde spam
fue llamado con argumentos no válidos.
Desafortunadamente, esto no es lo que sucedería, al menos por defecto, usando Python. En cambio, la última línea del traceback se referirá a algún lugar en el interior del código de la biblioteca, donde la excepción fue realmente raise
'd, lo que sería bastante oscuro para el público previsto de este traceback particular.
Ejemplo:
# spam.py (library code)
def spam(ham, eggs):
'''
Do something stupid with ham and eggs.
At least one of ham and eggs must be True.
'''
_validate_spam_args(ham, eggs)
return ham == eggs
def _validate_spam_args(ham, eggs):
if not (ham or eggs):
raise ValueError('if we had ham '
'we could have ham and eggs '
'(if we had eggs)')
# client.py (client code)
from spam import spam
x = spam(False, False)
Cuando corremos client.py
, obtenemos:
% python client.py
Traceback (most recent call last):
File "client.py", line 3, in <module>
x = spam(False, False)
File "/home/jones/spam.py", line 7, in spam
_validate_spam_args(ham, eggs)
File "/home/jones/spam.py", line 12, in _validate_spam_args
raise ValueError('if we had ham '
ValueError: if we had ham we could have ham and eggs (if we had eggs)
mientras que lo que queremos estaría más cerca de:
% python client.py
Traceback (most recent call last):
File "client.py", line 3, in <module>
x = spam(False, False)
ValueError: if we had ham we could have ham and eggs (if we had eggs)
... con el infractor código (x = spam(False, False)
) como la última línea del traceback.
Lo que necesitamos es una forma de informar el error "desde la perspectiva de la persona que llama" (que es lo que Carp::carp
deja hacer en Perl).
EDITAR: Para que quede claro, esta pregunta no es sobre LBYL vs EAFP, ni sobre precondiciones o programación por contrato. Lo siento si di esta impresión equivocada. Esta pregunta se trata de cómo generar un rastreo desde unos pocos (uno, dos) niveles en la pila de llamadas.
Edit2: módulo de Python traceback
es un lugar obvio para buscar un pitón-equivalente de Perl de Carp::carp
, pero después de estudiar durante algún tiempo yo no era capaz de encontrar alguna manera de utilizarlo para lo que yo quiero hacer. FWIW, Carp::carp
de Perl permite un ajuste fino de la trama inicial para la trazabilidad al exponer la variable global (por lo tanto de alcance dinámico) $Carp::CarpLevel
. Las funciones de biblioteca que no son API que pueden -out, local
-ize e incrementan esta variable en la entrada (por ejemplo, local $Carp::CarpLevel += 1;
). No veo nada ni remotamente como este módulo de Python traceback
. Entonces, a menos que me haya perdido algo, cualquier solución que use Python's traceback
tendría que tomar un rumbo diferente ...
estoy un poco familiarizado con el módulo de rastreo, pero no veo ninguna manera de usarlo por lo que quiero hacer Si tiene algo concreto en mente, me sería útil ver algún bosquejo de código. (También, vea mi último EDIT, para más información sobre cómo '$ Carp :: carpa' resuelve este problema.) – kjo
@kjo He editado mi respuesta para mostrar un enfoque posible use el módulo de rastreo –
@kjo, he agregado una segunda solución que permite usar un python equivalente a carpa sin ningún código de soporte. –