14 сентября 2010 г.

Отладка обратных вызовов (callback), Python, Pydev

Я пишу сайты на Django. Обычно разработка ведётся на локальной машине, а не на сервере :) И иногда приходится отлаживать коллбэки каких-то сервисов, например, IPN у PayPal. Проблема в том, что локальная машина недоступна из интернета и коллбэк просто не дойдёт до пункта назначения. Для решения этой проблемы есть несколько решений.

Удалённая отладка

Одно из решений - удалённая отладка. В этом случае код будет выполняться на удалённой машине. Это не очень удобный способ. Но кроме отладки коллбэков, в некоторых случаях просто бывает удобно отлаживать процесс, запущенный на удалённой машине - на сервере, например, при этом делать это из привычной среды разработки и иметь все возможности локальной отладки - пошаговое выполнение, просмотр переменных, стэка и т.д. Настроить удалённую отладку на Pydev несложно.

Всё что нужно уже идёт вместе с Pydev, а на их сайте есть хорошая инструкция как настроить удалённую отладку. Схема такая:

  1. На локальной машине (там где запущен Eclipse/Aptana с Pydev) запускаем remote debugger server с помощью кнопочки start the pydev server. У меня эта кнопочка находится в перспективе Debug:

    После запуска сервера во вкладке Debug появится запущенный сервер, а во вкладку Console добавится строчка что сервер запущен.

  2. На удалённой машине нужно вставить в код, который нужно отладить, такую строчку: import pydevd;pydevd.settrace();

    Эта строчка импортирует модуль, который идёт вместе с Pydev, а вызов settrace() остановит выполнение скрипта, предоставляя нам возможность удалённой отладки. Модуль pydevd, вместе с содержимым папки <eclipse path>\plugins\org.python.pydev.debug_x.x.x.xxxxxxxxxx\pysrc, нужно разместить там, где Python сможет найти эти файлы (в папках из переменной окружения PATH, или добавить туда свою папку);

  3. Пока мы имеем никак не связанные две машины - локальную и удалённую. Что бы они смогли обмениваться данными, настроим ssh туннелинг. pydevd на удалённой машине по умолчанию будет слать данные (после вызова settrace()) в порт 5678 (соответственно, remote debugger server слушает тот же порт). Добавим новый порт в настройках PuTTY:

Всё готово. Я настраивал удалённую отладку для работы с Django приложением, поэтому проверим её на такои примере - надо отладить код вьюхи index, которая выполняется, когда пользователь заходит на корень сайта.

  1. Добавляю строчку:

    def index(request):
        import pydevd;pydevd.settrace()
        a = 1 + 2
        b = a * 2
        ...
        return direct_to_template(request, ...)
    
  2. Перезапускаю сервер, выполняющий Django приложение (Apache):

    service httpd restart

  3. Захожу браузером в корень сайта - выполнение кода останавливается, а Aptana на локальной машине позволяет отлаживать код.

Вот хорошее описание как работает settrace():

After passing through the pydevd.settrace() it should stop in any breakpoints you have defined. You can even call pydevd.settrace(suspend=False) if you don't want it to stop at the settrace call, only on defined breakpoints. There is a catch though, by default it'll only trace the current thread, if you want it to trace other threads in this call, you have to call settrace(trace_only_current_thread=False).

Т.е. лучше поместить вызов settrace() куда-нибудь в django.wsgi в код запуска приложения.

С удалённой отладкой есть такая проблема. Скрипт выполняется на сервере, соответственно файлы нужно модифицировать на сервере. Кроме того нужно перезапускать сервер, выполняющий эти скрипты, либо как-то автоматизировать перезапуск. Это существенные минусы, хотя и можно немного улучшить ситуацию, например, настроить в эклипсе соединение с сервером и загружать локальные файлы на сервер прямо из эклипса, или править файлы на сервере (тоже из эклипса).

В общем, удалённая отладка очень неудобна, и имеет смысл её применять в очень особых случаях.

Перенаправление портов

Другой подход заключается в том, что бы как-то сделать доступным локальную машину из интернета. Этот вариант гораздо удобнее удалённой отладки, ведь отладка будет происходить польностью на локальной машине.

Один из вариантов - настроить форвардинг портов ssh. Внешний сервис будет посылать коллбэк нашему серверу на специальный порт, а этот порт с помощью ssh будет перенаправляться на локальную машину с запущенным под отладчиком приложением.

  1. Для начала нужно разрешить демону sshd принимать запросы с удалённых адресов (по-умолчанию он принимает запросы только с localhost). Правим файл /etc/ssh/sshd_config, раскомментируем/добавляем строчку GatewayPorts yes:

    mcedit /etc/ssh/sshd_config

    Перезапустим sshd:

    service sshd restart

  2. Затем настраиваем PuTTY что бы перенаправлял порт удалённой машины (пусть будет 5679) на порт локальной машины (у меня django devserver работает на 9999):

  3. Запускаем PuTTY, запускаем django dev server под отладчиком, и заходим браузером по адресу http://<server.domain>:5679/ и пользуемся нормальной отладкой с бряками и прочим.

Оба способа требуют хорошего подключения к серверу. У меня PuTTY часто терял подключение и даже вылетал. Не очень приятно, но думаю для отладки пары коллбэков хватит :)

PS. Есть ещё как минимум один вариант - для Opera Unite есть приложение Web Proxy, которое делает почти тоже самое что и перенаправление портов, только сервер будет оперовский и без PuTTY.

Комментариев нет:

Отправить комментарий