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.

21 июля 2010 г.

Компилирование Python пакетов

Недавно обновил Python до версии 2.7. Это правильно, потому что эта ветка будет поддерживаться долго-долго, параллельно с веткой 3.x, плюс она имеет некоторые клёвые фичи ветки 3.x (бэкпорт).

Но тут возникла проблема. Не все пакеты имеют скомпилированные установщики для Windows под Python 2.7. А установить такие пакеты средствами Python, такими, как pip, easy_install или setup.py install, не выходит, т.к. таким пакетам нужно откомпилировать кое-какой C/C++ код. А компилятора у меня нет. Значит, надо установить и настроить! :)

Можно пойти тремя путями:

  • Установить MS Visual Studio. Если я правильно понял, это не очень удобный вариант;
  • Установить Cygwin. Он создаёт Linux окружение в Windows. Тоже не очень хороший вариант, т.к. он будет компилировать код, который будет работать в этом Linux-окружении. В отличие от MinGW. К тому же у меня не получилось его завести после n времени;
  • Установить MinGW. Этот проект позволяет компилировать код в родной для Windows формат. Получающимся файлам не нужно никакое Linux окружение. Этот вариант и будем использовать.

Установка MinGW очень простая - заходим на сайт, качаем установщик, отмечаем нужные компоненты - c++ компилятор, fortran компилятор, mingw make, он скачает их из интернета.

После установки нужно добавить папку MinGW\bin\ в переменную окружения PATH. После установки MinGW у нас есть необходимые инструменты для компилирования C/C++/Fortran кода.

Теперь нужно настроить distutils для работы с этими инструментами. Создаём файл Python27\Lib\distutils\distutils.cfg и вставляем туда такой текст:

[build]
compiler = mingw32

Готово! Проверяем на пакете numpy. Скачиваем исходники (.tar.gz), распаковываем, выполняем:

cd numpy-1.4.1
setup.py install

Всё должно пройти хорошо и мы должны получить скомпилированный и установленный пакет numpy.

Кроме установки, setup.py может выполнять много других команд. Например, такая команда создаст установщик для Windows:

setup.py bdist_wininst

Получится файл numpy-1.4.1.win32-py2.7.exe:

Альтернативный способ, без редактирования файла distutils.cfg - указать компилятор в параметрах командной строки:

setup.py install build -c mingw32

Но не все пакеты могут быть так легко установлены. Некоторым нужно разрешить зависимости. Например, matplotlib как минимум не компилируется без freetype и без его исходников. Но это уже другая история.

Ссылки:

4 июня 2010 г.

22 марта 2010 г.

demalexx.org

А потому что дорого свой сервак. Да, blogger не умеет markdown, для этого я взял js реализацию Showdown, пишу текст на markdown, вставляю html в blogger. Имею real-time предпросмотр, удобнее чем в blogger.

Да, blogger не умеет картинки. Для этого есть Dropbox. Картинка вот например: Два типа людей

Это было весело, да...

18 декабря 2009 г.

Переезд

Наверное уже можно :)

http://demalexx.org

21 ноября 2009 г.

Сервисы Google и Python

Наткнулся в журнале Хакер на статью про использование сервисов Гугла в Питоне. Мощная штука! :) Можно работать, например, с блоггером, почтой, таблицами, документами и т.д.

Начать нужно с Google Data Protocol - страницы протокола, который используется для работы с API гугловых сервисов. Там есть библиотечки для разных языков.

Хотя, это API какое-то странное и не очевидное... Вот простой пример, который печатает в консоль все посты дефолтного блога пользователя demalexx@gmail.com.
# -*- coding:utf-8 -*-

'''This script prints all blog posts from blogger.com'''

from gdata import service
import gdata
import atom

blogger_service = service.GDataService('demalexx@gmail.com', 'password')
blogger_service.source = ''
blogger_service.service = 'blogger'
blogger_service.account_type = 'GOOGLE'
blogger_service.server = 'www.blogger.com'
blogger_service.ProgrammaticLogin()

query = service.Query()
query.feed = '/feeds/default/blogs'
feed = blogger_service.Get(query.ToUri())

blog_id = feed.entry[0].GetSelfLink().href.split("/")[-1]

feed = blogger_service.GetFeed('/feeds/' + blog_id + '/posts/default')

print feed.title.text
for entry in feed.entry:
    print "\t" + entry.title.text.decode('utf-8')
Вывод:
D:\Projects\python\google>get_blogger_posts.py
race1
    Сервисы Google и Python
    PAP Affiliate и eAccelerator
    SSH - аутентификация ключом
...

20 ноября 2009 г.

PAP Affiliate и eAccelerator

На сайте стоит eAccelerator и потом я поставил PAP Affiliate. С самого начала этот пап работал очень медленно. Настолько медленно, что оставлял после себя процессы httpd, работающие по несколько часов и потребляющие все ресурсы процессора. Единственный выход был в перезагрузке Апача, но это спасало не надолго.

Интересна реакция саппорта. Они просили проверить настройки электропочты. Типа проблема в этом. Хотя письма как раз отправлялись. Попробовал я поменять эти настройки - в настроках PAP сделал отправку писем не функцией mail(), а используя SMTP сервер - ничего лучше не стало, конечно.

Как временная мера - установил лимит на выполнение скриптов из папки PAP в 30 секунд :)

В общем в итоге всё оказалось просто. PAP не работает с eAccelerator. Вот страница у них на сайте, где говорится что они знакомы с проблемой, и ничего не собираются с ней делать: http://support.qualityunit.com/knowledgebase/post-affiliate-pro/troubleshooting/eaccelerator-module-installed-at-server.html.

Что бы решить проблему нужно выключить eAccelerator для скриптов из папки PAP. Для этого я создал файл /var/www/vhosts/centurysupplements.com/conf/vhost.conf (конфиг Апача для виртуального хоста), и написал туда такой текст:
<Directory /var/www/vhosts/centurysupplements.com/httpdocs/affiliate>
    php_admin_value eaccelerator.enable 0
</Directory>
Т.е. выключить eAccelerator для папки /var/www/vhosts/centurysupplements.com/httpdocs/affiliate (там установлен PAP).

Теперь PAP просто летает, а eAccelerator работает для всего остального сайта.

PS. Удалил eAccelerator, заменил его APC. Он, говорят лучше, плюс от создателей PHP. И PAP с ним работает.