Блог - Linux, программирование, Я!

PythonКак правильно распарсить access лог Nginx/Apache

Наверняка у многих возникает такая задача - извлечь какие-то данные из Access лога Apache или Nginx. Записи лога обычно выглядят как то так:

91.77.238.152 - - [02/Dec/2013:20:31:45 +0400] "GET /blog/2012/01/31/plagin-l2tp-dlya-networkmanager/ HTTP/1.1" 200 70666 "http://yandex.ru/clck/jsredir?text=%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%20l2tp%20%D0%B4%D0%BB%D1%8F%20networkmanager&uuid=..." "Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.1.16) Gecko/20111108 Iceweasel/3.5.16 (like Firefox/3.5.16)"

На первый взгляд кажется, что форматирование этой строки какое-то нелогичное и ничем не оправданное: где то значения заключены в кавычки, где-то в квадратные скобки, где то значение записано как есть. Из за этого кто-то пытается сконструировать огромную нечитаемую регулярку, которую приходится каждый раз писать заново, из за того, что через неделю понять что же она делает нереально. Кто то разбивает строку по пробелам и надеется на лучшее, при этом поле даты разрезается на 2 части а User-Agent превращается вообще в необрабатываемое месиво.

Мы же поступим иначе - попробуем найти систему в структуре этой строки и напишем полноценный лексический анализатор. (далее...)

ПрограммированиеБенчмарк HTML парсеров

Переписывал на работе кусок одного сервиса с Python на Erlang. Сам сервис занимается тем, что скачивает по HTTP значительное количество однотипных HTML страниц и извлекает из них некоторую информацию. Основная CPU нагрузка сервиса приходится на парсинг HTML в DOM дерево.

Сперва захотелось сравнить производительность Erlang парсера mochiweb_html с используемым из Python lxml.etree.HTML(). Провел простейший бенчмарк, нужные выводы сделал, а потом подумал что неплохо было бы добавить в бенчмарк ещё парочку-другую парсеров и платформ, оформить покрасивее, опубликовать код и написать статью.
На данный момент успел написать бенчмарки на Erlang, Python, PyPy, NodeJS и С в следующих комбинациях:

  • Erlang - mochiweb_html
  • CPython - lxml.etree.HTML
  • CPython - BeautifulSoup 3
  • CPython - BeautifulSoup 4
  • CPython - html5lib
  • PyPy - BeautifulSoup 3
  • PyPy - BeautifulSoup 4
  • PyPy - html5lib
  • Node.JS - cheerio
  • Node.JS - htmlparser
  • Node.JS - jsdom
  • C - libxml2 (скорее для справки)

В тесте сравниваются скорость обработки N итераций парсера и пиковое потребление памяти.

Интрига: кто быстрее - Python или PyPy? Как сказывается иммутабельность Erlang на скорости парсинга и потреблении памяти? Насколько быстра V8 NodeJS? И как на всё это смотрит код на чистом C. (далее...)

PythonСамая короткая запись асинхронных вызовов в tornado v2, или патчим Python AST

Меня очень заинтересовала статья Самая короткая запись асинхронных вызовов в tornado или патчим байткод в декораторе, не столько с практической точки зрения, сколько с точки зрения реализации.
Всё-таки модификация байткода в рантайме это слишком опасная и ненадежная операция. И уж наверняка не поддерживаемая альтернативными интерпретаторами Python.

Попробуем исправить этот недостаток способом, который для этого куда больше предназначен и который применяется для схожих целей во многих других языках (я точно встречал в Lisp и Erlang). Этот способ - модификация Абстрактного синтаксического дерева (AST) программы.
(далее...)

PythonРаздача больших файлов через сервер TornadoWEB

TornadoWeb - это легковесный веб-сервер, написанный на Python и использующий неблокирующие сокеты и epool/kqueue для работы с сетью.Сам по себе сервер неплохой, довольно популярный. Привлекает своим крайне простым API (по сравнению с тем-же Twisted) и высокой производительностью.

Первый вопрос, который может возникнуть - "зачем раздавать большие файлы через Tornado?" Ведь даже официальная документация рекомендует использовать для этого Nginx. Что-ж, в большинстве случаев так и есть. Но ситуации могут быть разные. В моём случае через Tornado успешно раздавалось большое количество мелких страничек, хранящихся в SQLite и один большой файл на 200МБ со списком всех доступных URL. Поднимать ради одного этого файла Nginx совершенно не хотелось.

Второй вопрос - "ну так в чем проблема - раздавай на здоровье!". Вот тут мы и сталкиваемся с неприятной особенностью этого сервера - стандартный StaticFileHandlerзагружает весь файл целиком в память перед тем как отдать его клиенту ( пруфлинк). Помимо этого, занятая память не освобождается, если клиент разорвал подключение не скачав весь файл целиком.

Вот эти 2 проблемы и будем решать. (далее...)

PythonИспользование Django ORM отдельно от Django

Понадобилось использовать Django ORM вне контекста самой Django. Конечно, проще и правильнее было бы использовать SQLAlchemy т.к. она рассчитана на такое использование, но мне нужно было написать паука, сохраняющего данные в БД и веб-интерфейс к этим данным. Веб-интерфейс точно решил делать на Django, а в пауке использовать те-же самые модели, чтобы не проделывать одну и ту же работу дважды. Т.к. паук был первым этапом работ а админка - вторым, появилась необходимость создавать таблицы из моделей без использования "syncdb".

В качестве основы использовалкод модуля django-standalone истатью Django ORM без Джанги -эта статья практически полностью решает проблему, но есть и несколько недостатков:

  • Модели для создания таблиц нужно перечислять вручную
  • Не создаются внешние ключи
  • По - мелочи - нужно каждой модели вручную задавать app_label

Попытаемся исправить эти недостатки.

(далее...)

PythonПлагин Vkontakte.ru для Gwibber

Вступление

Gwibber + VkontakteНе так давно решил вплотную познакомиться со всей кухней OpenSource со стороны разработчика и в качестве первой пробы решил написать плагин к Gwibber для поддержки Вконтакте. Надо сказать, что тикет на Launchpad на эту тему висит с середины 2010 года (датирован 2010-05-01) с довольно длинным обсуждением, было несколько попыток реализовать поддержку, но готового решения никто не предложил. Помимо Launchpad, появился топик на форуме Ubuntu.ru, в котором топикстартер сообщил, что реализовал поддержку ВК, но код так никому и не показал.

Так что в начале декабря взялся за работу и через 2 месяца рабочая протестированная версия плагина была готова. На данный момент я уже отправил запрос о включении плагина в официальную ветку Gwibber и буквально сегодня разработчики отметили его для включения в релиз 2.91.5.
Описание функционала, инструкция для желающих протестировать плагин в работе уже сейчас под катом... (далее...)

PythonSVN хак — пишу граббер

Сегодня на хабре был опубликован отчет об обнаруженной уязвимости (точнее о распространенной ошибке при работе через) SVN.

Суть его заключается в том, что если сайт разрабатывается через систему SVN, то многие разработчики вместо команды svn export просто копируют директорию проекта из рабочих файлов SVN на продакшн - сервер и забывают, что при этом копируются скрытые папки ./svn в том числе ./svn/entries - список содержимого каталога и ./svn/text-base/ в которой и находятся исходники с дополнительным расширением .svn-base В результате можно стянуть исходный код сайта, т.к. веб-сервер не всегда передает интерпретатору файлы с расширением .svn-base и они будут передаваться plaintext-ом

Так что, не теряя времени, написал на Python граббер для сайтов, которые еще не успели дыры закрыть...

Последняя версия - СКАЧАТЬ

Версия 0.5 - СКАЧАТЬ
Версия 0.4 - СКАЧАТЬ
Версия 0.3 - СКАЧАТЬ
Версия 0.2 - СКАЧАТЬ
Версия 0.1 - СКАЧАТЬ

PythonИзучаю Python

Давно хотел изучить какой-нибудь новый для меня язык программирования. А то все PHP да JavaScript... Скучновато становится))

Собственно, самостоятельно начать было сложно, создал топик на Хабре чтобы поинтересоваться, что могут посоветовать по этому поводу бывалые программисты. В итоге к единому мнению не пришли, но почву для размышлений мне подкинули.

Приступим! (далее...)