Depuración de código de Python de forma remota en Linux en Visual Studio

En este artículo, explorará cómo configurar la instalación de Visual Studio para admitir la depuración de código de Python en equipos Linux remotos. Este tutorial se basa en Visual Studio 2019 16.6.

En Visual Studio se pueden iniciar y depurar aplicaciones de Python de manera local y remota en un equipo Windows. Visual Studio también admite la depuración remota en un sistema operativo, un dispositivo o una implementación de Python diferentes a CPython mediante la biblioteca debugpy.

En Visual Studio 2019 16.4 y versiones anteriores se usa la biblioteca ptvsd. En Visual Studio 2019 versión 16.5 y posteriores, la biblioteca debugpy sustituye a ptvsd. Al usar debugpy, el código de Python que se depura hospeda el servidor de depuración al que puede asociar Visual Studio. Este hospedaje requiere una pequeña modificación en el código para importar y habilitar el servidor. También es posible que tenga que ajustar las configuraciones de red o firewall en el equipo remoto para permitir conexiones TCP.

Requisitos previos

  • Visual Studio instalado con compatibilidad con cargas de trabajo de Python. Para obtener más información, consulte Instalación de la compatibilidad con Python en Visual Studio.

  • Un equipo remoto que ejecute Python en un sistema operativo como Mac OSX o Linux.

  • El puerto 5678 (entrada) abierto en el firewall del equipo remoto, que es el valor predeterminado para la depuración remota.

Configurar un equipo Linux

Puede crear fácilmente una máquina virtual de Linux en Azure y acceder mediante Escritorio remoto desde Windows. Ubuntu para la máquina virtual es cómodo porque Python está instalado de forma predeterminada. Si tiene una configuración diferente, consulte Instalación de intérpretes de Python para otras ubicaciones de descarga de Python.

Configuración del firewall

El puerto de entrada 5678 debe estar abierto en el firewall del equipo remoto para admitir la depuración remota.

Para obtener información sobre cómo crear una regla de firewall para una máquina virtual de Azure, consulte los siguientes artículos:

Preparar el script para la depuración

Siga estos pasos para preparar un script para depurar el código de Python en Linux.

  1. En el equipo remoto, cree un archivo de Python denominado guessing-game.py con el código siguiente:

    import random
    
    guesses_made = 0
    name = input('Hello! What is your name?\n')
    number = random.randint(1, 20)
    print('Well, {0}, I am thinking of a number between 1 and 20.'.format(name))
    
    while guesses_made < 6:
        guess = int(input('Take a guess: '))
        guesses_made += 1
        if guess < number:
            print('Your guess is too low.')
        if guess > number:
            print('Your guess is too high.')
        if guess == number:
            break
    if guess == number:
        print('Good job, {0}! You guessed my number in {1} guesses!'.format(name, guesses_made))
    else:
        print('Nope. The number I was thinking of was {0}'.format(number))
    
  2. Instale el paquete debugpy en su entorno con el comando pip3 install debugpy.

    Nota:

    Se recomienda registrar la versión de debugpy que está instalada en caso de que la necesite para solucionar problemas. La lista debugpy también muestra las versiones disponibles.

  3. Habilite la depuración remota agregando el código siguiente en la parte superior del archivo guessing-game.py antes de otro código. (Aunque no es un requisito estricto, es imposible depurar subprocesos en segundo plano generados antes de la llamada a la función listen).

    import debugpy
    debugpy.listen(('0.0.0.0', 5678))
    
  4. Guarde el archivo y, a continuación, ejecute el programa:

    python3 guessing-game.py
    

    La llamada a la función listen se ejecuta en segundo plano y espera las conexiones entrantes mientras interactúa con el programa. Si lo desea, puede llamar a la función wait_for_client después de llamar a la función listen para bloquear el programa hasta que se asocie el depurador.

Sugerencia

Además de las funciones listen y wait_for_client, debugpy también proporciona una función auxiliar breakpoint. Esta función actúa como punto de interrupción mediante programación si el depurador está asociado. Otra función, is_client_connected1, devuelve True si el depurador está asociado. No es necesario comprobar este resultado antes de llamar a ninguna otra función debugpy.

Asociar desde Herramientas de Python de forma remota

Los pasos siguientes muestran cómo establecer un punto de interrupción para detener el proceso remoto.

  1. Cree una copia del archivo remoto en el equipo local y ábralo en Visual Studio. No importa dónde se encuentre el archivo, pero su nombre debe coincidir con el nombre del script en el equipo remoto.

  2. (Opcional) Para tener IntelliSense para debugpy en el equipo local, instale el paquete de debugpy en su entorno de Python.

  3. Seleccione Depurar>Asociar al proceso.

  4. En el cuadro de diálogo Asociar al proceso, establezca Tipo de conexión en Remota de Python (debugpy).

  5. En el campo Destino de conexión, escriba el comando tcp://<ip_address>:5678.

    • tcp:// especifica el tipo de conexión como Protocolo de control de transmisión (TCP).
    • <ip_address> es la dirección IP del equipo remoto, que puede ser una dirección explícita o un nombre como myvm.cloudapp.net.
    • :5678 es el número de puerto de depuración remota.
  6. Pulse Entrar para rellenar la lista de procesos de debugpy disponibles en el equipo:

    Screenshot that shows how to enter the connection target to see a list of available debugpy processes.

    Si inicia otro programa en el equipo remoto después de rellenar esta lista, haga clic en el botón Actualizar.

  7. Seleccione el proceso para depurar y después seleccione Adjuntar o haga doble clic en el proceso.

  8. Visual Studio cambia al modo de depuración mientras el script continúa ejecutándose en el equipo remoto, lo que proporciona todas las capacidades normales de depuración.

    Puede establecer un punto de interrupción en la línea if guess < number: y después cambiar al equipo remoto y escribir otro intento. Visual Studio del equipo local se detiene en el punto de interrupción, muestra las variables locales, etc.:

    Screenshot that shows how Visual Studio pauses debugging when a breakpoint is hit.

  9. Al detener la depuración, Visual Studio se desasocia del programa. El programa continúa ejecutándose en el equipo remoto. debugpy también sigue escuchando para conectar depuradores, por lo que se puede volver a conectar al proceso en cualquier momento.

Solución de problemas de conexión

Revise los siguientes puntos para ayudar a solucionar problemas con la conexión.

  • Asegúrese de haber seleccionado Remota de Python (debugpy) para Tipo de conexión.

  • Confirme que el secreto en Destino de conexión coincide exactamente con el secreto en el código remoto.

  • Confirme que la dirección IP en Destino de conexión coincide exactamente con la del equipo remoto.

  • Compruebe que el puerto de depuración remota del equipo remoto está abierto y que el destino de la conexión incluye el sufijo del puerto, como :5678.

    Para usar un puerto diferente, especifique el número de puerto de la llamada a la función listen, como en debugpy.listen((host, port)). En este caso, asegúrese de abrir el puerto concreto en el firewall.

  • Confirme que la versión debugpy instalada en el equipo remoto (tal como la devuelve el comando pip3 list) coincide con la versión de Visual Studio Python Tools (PTVS).

    En la tabla siguiente se enumeran los pares de versión válidos. Según sea necesario, actualice la versión de debugpy en el equipo remoto.

    Visual Studio Herramientas de Python debugpy
    2019 16.6 1.0.0b5 1.0.0b5
    2019 16.5 1.0.0b1 1.0.0b1

Nota

Las versiones de Visual Studio 2019 16.0 a 16.4 usaban ptvsd, no debugpy. El proceso de este tutorial para esas versiones es similar, pero los nombres de función son diferentes. Visual Studio 2019 16.5 usa debugpy, pero los nombres de función eran los mismos que los de ptvsd. En lugar de listen, usaría enable_attach. En lugar de wait_for_client, usaría wait_for_attach. En lugar de breakpoint, usaría break_into_debugger.

Uso de ptvsd 3.x para la depuración heredada

El depurador heredado ptvsd 3.x es el valor predeterminado en Visual Studio 2017 versión 15.7 y anteriores.

En función de la configuración de Visual Studio, es posible que tenga que usar ptvsd 3.x para la depuración remota:

  • Visual Studio 2017, versión 15.7 y anteriores con Python 2.6, 3.1 a 3.4 o IronPython
  • Visual Studio 2019, versión 16.5 y posteriores con Python 2.6, 3.1 a 3.4 o IronPython
  • Versiones 4.x anteriores

Si la configuración implementa un escenario de versión anterior, Visual Studio muestra el error El depurador no admite este entorno de Python.

Configuración de la depuración remota

Para prepararse para la depuración remota con ptvsd 3.x, siga estos pasos:

  1. Configure el secreto, que se usa para restringir el acceso al script en ejecución.

    En ptvsd 3.x, la función enable_attach requiere que transfiera un "secreto" como primer argumento.

    • Al asociar el depurador remoto, escriba el secreto con el comando enable_attach(secret="<secret>").

    Aunque puede permitir que cualquier usuario se conecte con el comando enable_attach(secret=None) , no se recomienda esta opción.

  2. Cree la dirección URL de destino de conexión con el formato tcp://<secret>@<ip_address>:5678.

    • tcp:// especifica el tipo de conexión como TCP.
    • <secret> es la cadena transferida con la función enable_attach en el código de Python.
    • <ip_address> es la dirección IP del equipo remoto, que puede ser una dirección explícita o un nombre como myvm.cloudapp.net.
    • :5678 es el número de puerto de depuración remota.

Conexión segura con el protocolo TCPS

De forma predeterminada, la conexión al servidor de depuración remota de ptvsd 3.x solo está protegida por el secreto y todos los datos se transfieren como texto sin formato. Para una conexión más segura, ptvsd 3.x admite SSL mediante la forma segura del protocolo TCP o TCPS.

Siga estos pasos para configurar ptvsd 3.x para trabajar con el protocolo TCPS:

  1. En el equipo remoto, use el comando openssl para generar archivos independientes para la clave y el certificado autofirmado:

    openssl req -new -x509 -days 365 -nodes -out cert.cer -keyout cert.key
    
    • En el símbolo del sistema openssl, escriba el nombre de host o la dirección IP que use para conectarse para el Nombre común.

    Para obtener más información, consulte Certificados autofirmados en la documentación del módulo ssl de Python. Tenga en cuenta que el comando descrito en la documentación de Python genera solo un único archivo combinado.

  2. En el código, modifique la llamada a la función enable_attach para incluir los argumentos certfile y keyfile mediante los nombres de archivo como valores. Estos argumentos tienen el mismo significado que para la función estándar ssl.wrap_socket de Python.

    ptvsd.enable_attach(secret='my_secret', certfile='cert.cer', keyfile='cert.key')
    

    También puede realizar el mismo cambio en el archivo de código en el equipo local. Dado que este código no se ejecuta realmente, no es estrictamente necesario.

  3. Reinicie el programa de Python en el equipo remoto, para que esté listo para la depuración.

  4. Proteja el canal agregando el certificado a la CA raíz de confianza en el equipo Windows con Visual Studio:

    1. Copie el archivo de certificado desde el equipo remoto al equipo local.

    2. Abra el Panel de control y vaya a Herramientas de Windows>Administrar certificados de equipo.

    3. En el cuadro de diálogo certlm [Certificates - local computer] expanda el nodo Entidades de certificación raíz de confianza, haga clic con el botón derecho en Certificados y seleccione Todas las tareas>Importar.

    4. Busque y seleccione el archivo .cer copiado desde el equipo remoto.

    5. Continúe con las indicaciones del cuadro de diálogo para completar el proceso de importación.

  5. Repita el proceso de asociación en Visual Studio, como se ha descrito anteriormente en Asociación desde Herramientas de Python de forma remota.

    Para esta instancia, defina tcps:// como protocolo para el Destino de conexión (o Calificador).

    Screenshot that shows how to specify TCPS as the remote debugging transport with SSL.

Solución de problemas de conexión

Durante el intento de conexión, Visual Studio podría encontrar problemas. Revise los siguientes escenarios y realice las acciones adecuadas, según sea necesario.

  • Visual Studio avisa sobre posibles problemas de certificado cuando se conecta a través de SSL.

    Acción: puede omitir el mensaje y continuar.

    Precaución

    Tenga en cuenta que, aunque el canal todavía está cifrado contra ataques de interceptación, puede estar abierto a ataques de tipo "Man in the Middle".

  • Visual Studio muestra la advertencia de que el certificado remoto no es de confianza.

    Problema: el certificado no se agrega correctamente a la CA raíz de confianza.

    Acción: vuelva a comprobar los pasos para agregar el certificado a la CA raíz de confianza en el equipo Windows e inténtelo de nuevo.

    Screenshot of the warning that says the remote SSL certificate isn't trusted.

  • Visual Studio muestra la advertencia de que el nombre del certificado remoto no coincide con el nombre de host.

    Problema: no se ha especificado el nombre de host o la dirección IP adecuados para el Nombre común del certificado.

    Acción: vuelva a comprobar los pasos descritos en Protección de la conexión con TCPS. Asegúrese de usar el Nombre común correcto al crear el certificado e inténtelo de nuevo.

    Screenshot of the warning that says the remote SSL certificate doesn't match the hostname.