¿Generar una excepción del scope de la persona que llama?

Supongamos que tengo el siguiente script:

def do_not_call_on_one(i): if i == 1: raise ValueError("You never listen.") print "Success!" do_not_call_on_one(1) 

En excution, verá el siguiente rastreo:

 Traceback (most recent call last): File "test.py", line 7, in  do_not_call_on_one(1) File "test.py", line 3, in do_not_call_on_one raise ValueError("You never listen.") ValueError: You never listen. 

¿Hay alguna manera de manipular la stack de llamadas, de manera que el error se emita desde la línea que realmente está causando el problema, como eso ?:

 Traceback (most recent call last): File "test.py", line 7, in  do_not_call_on_one(1) ValueError: You never listen. 

Esto ahorraría tiempo al desarrollador que de lo contrario se perdería al escanear la stack de llamadas, buscando la función utilizada incorrectamente, cuando el comportamiento correcto podría definirse con anticipación.

¿Hay algo en Python que permita una excepción para usar un rastreo modificado?

Actualizar

Hay buitins que están replicando esta funcionalidad:

 # In test.py: int('a') # Executing 'python test.py' yields: Traceback (most recent call last): File "test.py", line 1, in  int('a') ValueError: invalid literal for int() with base 10: 'a' 

Nota: la raise ValueError no desciende a la función int() para mostrar un montón de ámbitos inútiles (especialmente el inútil raise ValueError ).

tl; dr: probablemente sí, pero no puedo imaginar que sea una buena idea.

Voy a asumir que podríamos, si nos esforzamos lo suficiente, falsificar una stack de llamadas para mostrar una excepción proveniente de un lugar diferente. Pero no creo que sea una buena idea.

En primer lugar, generalmente se entiende que la función que genera una excepción no siempre tiene la culpa. Si alguien rompió el contrato y te pasó un parámetro que no esperas, está bien hacer una excepción. Si se pretende que esto cubra su trasero al boost la excepción en el ámbito de la persona que llama para que nadie culpe a su función, creo que alguien (tal vez usted, tal vez el sistema de “culpa” de sus pruebas automáticas) necesita volver a pensar cómo determinan la responsabilidad.

En segundo lugar, no creo que pueda definir muy bien el scope “correcto”. Podría imaginar que siempre debería plantearse en el ámbito de la persona que llama, porque claramente no es su culpa. Bueno, ¿y si tampoco es su culpa? ¿Debería cada función simplemente levantar las manos y decir “no fue mi culpa” cuando se produce una excepción? Muy pronto nuestros stacktraces no dirán nada en absoluto.

Incluso si tienes razón, y tu función es irreprochable, estás a punto de hacer que la vida de todos los demás sea un infierno, porque manipular la stack de llamadas para ocultar tu función hará que todos se rascen la cabeza y eliminarán pruebas valiosas para depurar la situación.

Esto puede parecer una buena idea, pero no creo que lo sea, y creo que si te pones en el lugar de alguien más, podrías comprender lo difícil que sería su vida tratar de usar una función que se comportó de esta manera.

Le sugeriría que detecte la excepción en el punto en el que desea estar en la parte superior de la stack de llamadas y luego aumente una nueva excepción envolviendo la anterior (de modo que pueda hacer referencia a la stack de llamadas original para saber qué excepción realmente causó el problema; después todo, ¿qué sucede cuando la print "Success!" falla porque, por ejemplo, alguien configura sys.stdout = int ?).


Después de navegar un poco, parece que https://stackoverflow.com/a/2615442/138772 es exactamente el tipo de respuesta que desea.