Руководство по удаленной отладке для Python
У вас когда-нибудь была серьезная ошибка в продакшене, которая не проявлялась на вашем компьютере даже после паритета почти со всем? Или, возможно, у вас нет особого выбора, кроме как работать непосредственно на сервере? Вы в конечном итоге используете печать или регистратор и просто бессистемно шлепаете их в разные места, надеясь увидеть, что происходит?
Я представлю вам удаленную отладку. Удаленная отладка позволяет интерактивно отлаживать код, которого нет на вашем компьютере, построчно. Это то, что другие описывали как «Божий дар» в отладке сложных проблем. С ним вы намного быстрее доберетесь до сути проблемы, и это чрезвычайно полезно, когда вам нужно перепроектировать проект.
Мы будем использовать пакет python, чтобы иметь общий API для работы.
- Visual Studio Code или Pycharm Professional
- Установлена либо зависимость ptvsd, либо pydevd_pycharm
pip install git+ssh://git@github.com/2upmedia/debugger_helper
Удаленная отладка с помощью Python состоит из пяти частей:
- сервер может связываться с вашей рабочей станцией
- у вас установлен соответствующий пакет IDE на сервере
- ваша IDE настроена для удаленной отладки правильно
- вы запускаете конфигурацию удаленной отладки в своей среде IDE справа
время - у вас есть тот же код, что и на сервере на вашей рабочей станции
Для каждой IDE существует пакет отладки, который служит отладчиком на
сервер. Он обменивается данными между сервером и IDE.
Вы должны убедиться, что сервер может общаться с вашим
рабочая станция. Это существенный часть удаленной отладки, потому что
есть пакеты TCP, отправленные туда и обратно между сервером и
ИДЕ. Эти пакеты сообщают о том, где установлены точки останова.
и информация о текущем стеке и переменных. Это
по сути, как работают все удаленные отладчики.
Самый простой способ разрешить линию связи TCP в обход любого
Проблемы с брандмауэром связаны с переадресацией портов. Это возможно с помощью ssh или
замазка.
С ssh просто проблема ssh -R LOCAL_PORT:IP:REMOTE_PORT user@host
для
обратный порт вперед и ssh -L LOCAL_PORT:IP:REMOTE_PORT user@host
для переадресации локального порта. Обычно вы использовали 127.0.0.1
для ИП и
те же номера портов, например,ssh -L 9000:127.0.0.1:9000 user@host
. Переадресация локального порта означает, что
сокет выделяется и прослушивается на вашей локальной машине и вперед
TCP-соединение с указанным удаленным портом на сервере. Реверс
переадресация порта означает, что сокет выделен и прослушивает ваш
удаленный компьютер и перенаправляет TCP-соединение на указанный локальный
порт на вашей машине. Visual Studio Code использует локальную переадресацию портов.
в то время как PyCharm требует обратного перенаправления портов.
Чтобы убедиться, что сервер может взаимодействовать с вашим компьютером, вы можете
выполните следующие команды на сервере:
$ openssl s_client -connect 127.0.0.1:9000
connect_to 127.0.0.1 port 9000: failed.
CONNECTED(00000004)
Если у вас установлен telnet, вы также можете попробовать…
$ telnet 127.0.0.1 9000
Trying 127.0.0.1...
Connected to localhost.
То, что вы ищете, это CONNECTED
для опенссл. Для телнета, если он
не выходит из telnet и через некоторое время не выдает ошибку, то это
значит подключено.
С точки зрения настройки это означает, что для PyCharm вам нужно запустить
сначала удаленная конфигурация IDE до запуск вашего скрипта Python во время
для кода Visual Studio вы запускаете его после ваш скрипт на питоне.
Параметры IDE удаленного отладчика определяют хост, порт и путь.
сопоставления. Сопоставление пути сопоставляет путь к папке с сервера на
путь к папке на локальном компьютере, чтобы отладчик мог подобрать
правильный файл.
Есть три переменные среды, которые модуль debugger_helper
использует:
START_DEBUGGER
DEBUGGER_HOST
(дефолт127.0.0.1
)DEBUGGER_PORT
(дефолт9000
)
START_DEBUGGER
переменная окружения должна быть установлена в любое непустое
значение, такое как 1
прямо перед запуском скрипта Python, который вы хотите
отлаживать.
Если все настроено правильно, отладчик должен немедленно остановиться.
в вашей точке останова. Если это не так, дважды проверьте каждый шаг.
- установить
ptvsd
на сервер - убедиться
pydevd-pycharm
не устанавливается, так как конфликтует сptvsd
- добавить локальный порт вперед с вашей машины на сервер через ssh (или
замазка) - добавьте следующее где-нибудь в самую верхнюю часть вашего python
проект. Например, если это приложение Flask с файлом app.py, который вы
может поместить его прямо вверху после вашего импорта.
import ptvsd
debugger_helper.attach_vscode(lambda host, port: ptvsd.enable_attach(address=(host, port), redirect_output=True))
- перейдите на панель отладки, добавьте конфигурацию, нажмите Python, затем
Удаленное подключение, установите хост на127.0.0.1
порт в9000
(или
порт для соответствия переадресации портов иDEBUGGER_PORT
переменная окружения). Вы должны увидеть эти значения вlaunch.json
. - за
remoteRoot
установите абсолютный путь к папке
содержащий ваш скрипт Python на сервере. Например, может быть
он находится в/www/pythonapp/
. Вы бы использовали это дляremoteRoot
. - установите точку останова, где вы хотите, чтобы отладчик остановился
- Запустите скрипт Python
$ START_DEBUGGER=1 python app.py
и жду
пока он не скажет, что готов подключиться к отладчику - Запустите конфигурацию удаленного подключения в Visual Studio Code.
- установить
pydevd_pycharm
на сервер - добавить обратный порт вперед с сервера на вашу машину через ssh
(или шпаклевка) - добавьте конфигурацию запуска для удаленной отладки Python. Установите хост на
127.0.0.1
и порт9000
. Сохрани это. - в поле конфигурации и сопоставления пути добавьте сопоставление для
абсолютный путь корня проекта к абсолютному пути того же
корень проекта, но на сервере - добавьте следующее где-нибудь в самую верхнюю часть вашего python
проект. Например, если это приложение Flask с файлом app.py, который вы
может поместить его прямо вверху после вашего импорта.
import pydevd_pycharm
debugger_helper.attach_pycharm(lambda host, port: pydevd_pycharm.settrace(host, port=port, stdoutToServer=True, stderrToServer=True))
- установите точку останова, где вы хотите, чтобы отладчик остановился. Вы можете установить
pydevd_pycharm.settrace(..., suspend=False)
если вы хотите избежать
отладчик не останавливается на строке, котораяsettrace
включен. - Запустите конфигурацию удаленной отладки в PyCharm.
- Запустите скрипт Python
$ START_DEBUGGER=1 python app.py
Одна из проблем с удаленной отладкой заключается в том, что по умолчанию, если вы вносите изменения в код, они не сразу отражаются на сервере. Если вы не знаете об этом, вы будете отлаживать более старую версию своего кода и видеть результаты, которые не коррелируют с внесенными вами изменениями.
Что вам нужно сделать, так это перезапустить процесс python при обновлении файла python. Мы можем сделать это автоматически с помощью watchgod
.
Итак, давайте пройдем через это.
- установить
watchgod
- создайте второй скрипт, который будет вызывать ваш основной скрипт Python, который включает отладчик. Это должно выглядеть примерно так:
import subprocess
def main():
subprocess.call(['python', 'app.py'])
- Запустите скрипт Python с помощью watchgod
$ START_DEBUGGER=1 watchgod debug.main
- Теперь в вашей среде IDE загрузите файл
Может быть, вы хотите включать отладчик только тогда, когда вам этого хочется?
Вот пример того, как это сделать в Flask. К сожалению, пакеты IDE не позволяют отключать отладчик после его включения, поэтому нам придется переборщить его, уничтожив процесс python. Это означает, что вам нужно будет снова запустить его вручную, или вы можете использовать что-то вроде gunicorn, которое создаст новый процесс после того, как увидит, что старый процесс уничтожен.
Следуйте вместе со мной.
- создайте функцию, которая будет проверять параметр запроса, а затем запускать
отладчик для запуска - обратите внимание на
call_immediately=True
аргумент вattach_pycharm
.
Это позволяет вам запускать отладчик на основе вашего набора правил. - вызовите эту функцию в теле маршрута
from flask import Flask, request
is_debugger_enabled = False
def attach_debugger():
global is_debugger_enabled
if request.args.get('START_DEBUGGER', ''):
debugger_helper.attach_pycharm(lambda host, port: pydevd_pycharm.settrace(host, port=port, stdoutToServer=True, stderrToServer=True, suspend=False), call_immediately=True)
is_debugger_enabled = True
elif is_debugger_enabled:
print('Trying to disable debugger that was enabled. Killing process to start a fresh one.')
sys.exit(1)
@app.route("/")
def hello():
attach_debugger()
message = "Hello Worlddd!"
return message
Теперь, когда вы научились выполнять удаленную отладку, вперед, запачкайте руки. После того, как вы воспользуетесь им, вы будете спрашивать себя, почему вы не использовали его раньше.
Удачной отладки!