Todas las variables no están definidas en el depurador de Python

Estoy enfrentando un problema muy extraño en Python 3.6. En el medio de mi código, llamo import pdb; pdb.set_trace() import pdb; pdb.set_trace() para depurar algún código.

Y luego no puedo depurar correctamente, por ejemplo:

 (Pdb) abc = 3 (Pdb) [abc for _ in range(2)] *** NameError: name 'abc' is not defined (Pdb) [abc, abc] [3, 3] 

Parece que cada vez que uso listas de comprensión, hay un problema de variable no definido. Sin embargo, si llamo al depurador justo después de abrir Python, no observo este comportamiento, todo funciona bien.

¿Alguna idea de por qué estoy teniendo este problema?

Esto sucede porque las comprensiones de listas se evalúan (en su mayoría) en un ámbito nested, y los ámbitos nesteds creados en pdb no pueden acceder a las variables locales del ámbito que se está inspeccionando. Sin embargo, pueden acceder a globales, y cuando inicias pdb inmediatamente después de abrir Python, lo estás ejecutando en un ámbito global, por lo que el abc que creas es global.

Esto también sucede con las listas de comprensión en exec y en declaraciones de clase. Desafortunadamente, no hay una solución mejor que “no usar las listas de comprensión allí”.

Esto se archiva como problema bpo # 21161 , pero se cierra como “no soluciona”.

El problema raíz es exactamente lo que dice la respuesta de user2357112 : Las comprensiones 1 funcionan al definir y luego ejecutar una función anidada oculta, pero las funciones definidas en pdb dentro de un marco no son funciones reales anidadas y no pueden acceder a las variables desde el scope del marco.

Existen soluciones alternativas (algunas de las cuales se mencionan en el problema de bpo, o lugares vinculados a ese problema), pero todas son simplemente variaciones inteligentes en uno de estos:

  • (lambda abc: [abc for _ in range(2)])(abc) (En otras palabras, defina una función y pase explícitamente los valores de los locales como argumentos en lugar de capturarlos).
  • [abc_ for abc_ in [abc] for _ in range(2)] (En otras palabras, use el hecho de que el iterable más externo es un argumento. 2 )
  • [loc['abc'] for loc in [locals()] for _ in range(2)] (En otras palabras, usa locals()['name'] lugar del name , y pasa a los locales como se indica arriba).
  • Use exec más cualquiera de las soluciones alternativas conocidas como horribles para las comprensiones en exec .
  • No utilice una comprensión, como sugiere el usuario2357112.

1. En Python 2.x, esto no es cierto para las comprensiones de lista, solo establece y dicta comprensiones y expresiones de generador. Pero Python 3 cambió la comprensión de las listas para hacerlas coherentes con las demás.

2. La función anidada oculta para una comprensión captura casi todos los nombres desde el ámbito del envolvente, pero la iterable más externa (la de la primera for ) es especial; en realidad, es un parámetro para la función oculta, y la expresión se evalúa en el ámbito de cierre y se pasa como valor del argumento.

Podrías probar el siguiente código:

 (Pdb) !import code; code.interact(local=vars()) Python 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 17:14:51) [GCC 7.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> [abc for _ in range(2)] 

Use Ctrl-D para regresar al indicador de pdb regular.