В последней заметке цикла будет рассмотрена самая, пожалуй, популярная бибилотека для визуализации графов graphviz. Биндинги для неё существуют для большинства популярных языков, в том числе и для python.
В отличии от рассмотренных ранее библиотек, graphviz предназначен исключительно для визуализации. Никаких алгоритмов внутри вы не найдёте. Поэтому чаще всего для манипулирования графами берут другие библиотеки, а полученные результаты представляют в виде dot-файла и отдают graphviz.
Записки обо всём, с чем приходится столкнуться по работе и что полезно не забывать. python, php, ZendFramework, NOSQL и т.д.
30 декабря 2011 г.
29 декабря 2011 г.
graph-tool [заметки о визуализации графов на python]
Третья заметка цикла посвящена python модулю graph-tool.
Базируется он на шибко резвой Boost Graph Library (BGL), а для визуализации использует graphviz.
Вообще, у BGL есть собственные биндинги на Python, однако
Итак, ближе к телу =)
Базируется он на шибко резвой Boost Graph Library (BGL), а для визуализации использует graphviz.
Вообще, у BGL есть собственные биндинги на Python, однако
- BGL-Python bindings are no longer being maintained.
- BGL не имеет инструментов для визуализации и нацеленна на использование в паре с graphviz.
- Готовые яйца под питон так и не появились, а ставить руками столь широкие вещи весьма трудоёмко.
Итак, ближе к телу =)
27 декабря 2011 г.
iGraph [заметки о визуализации графов на python]
Тема второй заметки о визуализации графов - библиотека igraph, имеющая биндинги под python. Для визуализации она использует библиотеку Cairo.
Документация библиотеки детальная и подробнейшая, но абсолютно лишена даже базовых примеров. Примеры однако доступны в бета версии туториала - там всё детально и подробно расписано, правда на R =)
Что касается визуализации - то данный раздел туториала ещё не сделан, что в целом не сильно мешает.
По аналогии с предыдущей заметкой мерить будем время работы и пиковое потребление памяти алгоритма расстановки графа. Исходные данные для работы взяты идентичные использованным в тойже первой заметке цикла.
Документация библиотеки детальная и подробнейшая, но абсолютно лишена даже базовых примеров. Примеры однако доступны в бета версии туториала - там всё детально и подробно расписано, правда на R =)
Что касается визуализации - то данный раздел туториала ещё не сделан, что в целом не сильно мешает.
По аналогии с предыдущей заметкой мерить будем время работы и пиковое потребление памяти алгоритма расстановки графа. Исходные данные для работы взяты идентичные использованным в тойже первой заметке цикла.
22 декабря 2011 г.
NetworkX [заметки о визуализации графов на python]
В заметках этого цикла будут рассмотренны несколько известных библиотек для визуализации графов, имеющие python-api.
В каждой заметке произведено сравнение скорости работы различных алгоритмов расстановки графов, а также примерные значения требуемой памяти.
Все сравнения я буду производить на невзвешенном ориентированном графе, включающем около 5 тысяч вершин и 18 тысяч рёбер.
Тестовая машинка - 4GB RAM + i3 540 3.07 GHz (x4).
Мерить будем пиковое значение памяти и время работы, поскольку для меня именно эти метрики являются критичными.
В каждой заметке произведено сравнение скорости работы различных алгоритмов расстановки графов, а также примерные значения требуемой памяти.
Все сравнения я буду производить на невзвешенном ориентированном графе, включающем около 5 тысяч вершин и 18 тысяч рёбер.
Тестовая машинка - 4GB RAM + i3 540 3.07 GHz (x4).
Мерить будем пиковое значение памяти и время работы, поскольку для меня именно эти метрики являются критичными.
7 декабря 2011 г.
NetBeans 7.* и Python
Из стандартных плагинов недоступна, однако же есть дев версия плагина.
- Идём в Tools -> Plugins -> Settings
- Жмакаем кнопочку Add
- Называем новый источник как угодно и вставляем ссыль http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastStableBuild/artifact/nbbuild/nbms/updates.xml.gz
- Обратно Available Plugins и жмакаем кнопочку Reload Catalog
- Ищем питон и ставим как обычно
Matplotlib и "FloatingPointError: underflow encountered in multiply"
Случилось мне столкнуться с мистической ошибкой при использовании matplotlib - библиотеки для рисования графиков и визуализации различных математических результатов, имеющей крайне Matlab Like API =)
Ошибка поставляется вместе с тучным traceback-ом, указывающим в итоге на
File "/usr/lib/python2.6/site-packages/numpy/ma/core.py", line 772, in __call__
return umath.absolute(a) * self.tolerance >= umath.absolute(b)
Тобишь ошибочка гдето внутрях ядра numpy, который библиотека юзает для своих целей.
Мистика заключается в том, что получить эту ошибку мне удалось только в связке версий 1.0.1 и 1.6.1 для matplotlib и numpy соответственно и только на python-е версии 2.6.5.
Ошибка поставляется вместе с тучным traceback-ом, указывающим в итоге на
File "/usr/lib/python2.6/site-packages/numpy/ma/core.py", line 772, in __call__
return umath.absolute(a) * self.tolerance >= umath.absolute(b)
Тобишь ошибочка гдето внутрях ядра numpy, который библиотека юзает для своих целей.
Мистика заключается в том, что получить эту ошибку мне удалось только в связке версий 1.0.1 и 1.6.1 для matplotlib и numpy соответственно и только на python-е версии 2.6.5.
10 ноября 2011 г.
Переводим cron-скрипты на Zend
Часто бывает, что cron-скрипты Zend приложений работают с теми же ресурсами, что и само приложение. Само собой, хочется перенести эти скрипты в привычное окружение зенда. Один из вариантов этой процедуры я и приведу.
Сразу оговорюсь - представленная реализация наверняка не самая лучшая и имеет множество изъянов, да и некоторые моменты у меня самого вызывают вопросы (просто когда понадобилось перенести все крон скрипты на зенд времени на детальное рассмотрение небыло совершенно). Поэтому буду рад всем фидбеками и замечаниям по коду =)
Сразу оговорюсь - представленная реализация наверняка не самая лучшая и имеет множество изъянов, да и некоторые моменты у меня самого вызывают вопросы (просто когда понадобилось перенести все крон скрипты на зенд времени на детальное рассмотрение небыло совершенно). Поэтому буду рад всем фидбеками и замечаниям по коду =)
19 октября 2011 г.
Zend cache manager + application.ini
Если кешей в приложении на зенде много (а так обычно и бывает, если у вас не хоум пейдж), рекомендую использовать их через специальный кеш менеджер, для которого существует соответствующий ресурс приложения.
В принципе, пример не сильно отличается от оф доки, разве что Вы также нарвались на упоминания в оной неких статический методов класса Zend_Cache_Manager, которых давно уже нет в коде =)
В принципе, пример не сильно отличается от оф доки, разве что Вы также нарвались на упоминания в оной неких статический методов класса Zend_Cache_Manager, которых давно уже нет в коде =)
17 октября 2011 г.
Отдача .PDF с помощью Zend
Бывает результатом работы action-а зенда является отдача файла.
По хорошему, файлы надо отдавать напрямую сервером, но бывает файл генерится автоматически да ещё отталкиваясь от прав. В этом случае от зенда уже не отмазаться =))
По хорошему, файлы надо отдавать напрямую сервером, но бывает файл генерится автоматически да ещё отталкиваясь от прав. В этом случае от зенда уже не отмазаться =))
13 октября 2011 г.
Zend и контроль доступа
Основы контроля доступа в приложениях на зенде разжёваны в интернетах вдоль и поперёк, поэтому подробно рассматривать эту тему я смысла не вижу.
Если вкратце:
Если вкратце:
- Создали ACL (статически или динамически)
- Определили роль юзера (как правило используются сессии)
- Проверили наличие привилегии к ресурсу
- Разрешили или отказали (способов отказа как правило несколько, от редиректа до исключения)
MongoDB под python (основы)
Решил запостить основные рецепты дабы не потерялись. Постепенно буду пополнять.
Сборник cоветов по компонентам Zend-а
В процессе рефакторинга часто встречаются различные "прелести", оставшиеся от старых версий тех или иных библиотек. Есть такие и у зенда. Буду дополнять этот сборник по мере работы.
29 сентября 2011 г.
Absolute URL and helper url() (view/action)
Столкнулся с забавным поведением внешне идентичных view хелпера url() и одноимённого action хелпера.
Делаем в контроллере следущее:
var_dump(
$this->view->url(array(), 'staticRegisterActivate', true),
$this->_helper->url->url(array(), 'staticRegisterActivate', true)
);
Видим два урла:
http://dseye.local/registertoken.html
и
/registertoken.html
Почему при одинаковом коде в обоих хелперах (там по 2 строки) мы получаем разный вариант? И заодно как же поступить - в контроллере нужно брать абсолютный урл по роутеру (не хотелось бы ещё и serverUrl туда приплетать).
Есть подозрение что хелпер вида что то ещё рендерит перед тем как роутер заасемблить, но подтверждений не нарыл =(
Так что тревога отменяется =)
Делаем в контроллере следущее:
var_dump(
$this->view->url(array(), 'staticRegisterActivate', true),
$this->_helper->url->url(array(), 'staticRegisterActivate', true)
);
Видим два урла:
http://dseye.local/registertoken.html
и
/registertoken.html
Почему при одинаковом коде в обоих хелперах (там по 2 строки) мы получаем разный вариант? И заодно как же поступить - в контроллере нужно брать абсолютный урл по роутеру (не хотелось бы ещё и serverUrl туда приплетать).
Есть подозрение что хелпер вида что то ещё рендерит перед тем как роутер заасемблить, но подтверждений не нарыл =(
UPD:
Докопался до причины =)) Оказалось это я сам переопределил стандартный хелпер вида для вывода абсолютных адресов
$this->view->serverUrl() . $router->assemble($urlOptions, $name, $reset, $encode)
28 сентября 2011 г.
Libcurl + c-ares (установка из сорцов)
c-ares дают возможность делать асинхронные
DNS запросы через pycurl (биндинги для libcurl). Мне это понадобилось для скоростного краба на питоне.
Под Windows все уже в порядке (.exe сетапник уже включает в себя скомпилированную поддержку 'c-ares').
На сервере же (Linux/FreeBSD) приходится ставить ручками (О_о). Далее приложу инструкцию для линуксы.
Под Windows все уже в порядке (.exe сетапник уже включает в себя скомпилированную поддержку 'c-ares').
На сервере же (Linux/FreeBSD) приходится ставить ручками (О_о). Далее приложу инструкцию для линуксы.
26 сентября 2011 г.
Zend_Log + application.ini + multiply logs
Понадобилось более сложная логика в Zend_Log и сразу хотелось сделать по хорошему, через application.ini
Удалось не всё =(
Удалось не всё =(
31 августа 2011 г.
10 августа 2011 г.
Простое кеширование вызовов Zend_Db_Table
Кеширование вызовов моделей (да и любых других классов) в зенде классически реализуется с помощью Zend_Cache_Frontend_Class.
В оригинале это выглядит примерно так:
Этот путь мне не понравился сразу по нескольким причинам.
Во первых - удваивание количества сущностей. Когда моделей много и Вы используете не по одной модельке на запрос монструозненько получается.
Во вторых - слишком много настроек кеша. Это очень хорошо и к месту, когда логика кеша сложна или нетривиальна. В моём случае весь кеш работает с одними и теми же настройками и совершать лишних телодвижений по его инстанцированию не хотелось бы.
В оригинале это выглядит примерно так:
Copy Source | Copy HTML
$model = MyModel();
- $model_cached = MyModelCached();
- $values_direct = $model->doStuff();
- $values_cached = $model_cached->doStuff();
Этот путь мне не понравился сразу по нескольким причинам.
Во первых - удваивание количества сущностей. Когда моделей много и Вы используете не по одной модельке на запрос монструозненько получается.
Во вторых - слишком много настроек кеша. Это очень хорошо и к месту, когда логика кеша сложна или нетривиальна. В моём случае весь кеш работает с одними и теми же настройками и совершать лишних телодвижений по его инстанцированию не хотелось бы.
28 июля 2011 г.
Zend + action helpers + application.ini
Action helpers иногда бывают очень полезны. В частности как замена плагинов фронт-контроллера с возможностью доступа к экземпляру конкретного контроллера действия. Примеры конфигурирования оных я и приведу.
14 июля 2011 г.
Zend_Db set timeout in app.ini
В интернете не нашёл примера для указания таймаута ресурса Db в app.ini.
resources.db.params.driver_options.2 = 6000 ;PDO::ATTR_TIMEOUTА всё потому, что в ini файле не исполнить PDO::ATTR_TIMEOUT =(
Zend_Db_Select + UNION + COUNT
Часто бывает нужно вывести часть данных и показать сколько ещё осталось. Сделать это можно разными способами, в данном случае я использую 2 отдельных запроса.
Весело становится когда запрос на выборку данных у нас составляется UNION-ами, к которому простой COUNT(*) не применить толком =)
Нашёл лаконичное решение через пагинатор.
Весело становится когда запрос на выборку данных у нас составляется UNION-ами, к которому простой COUNT(*) не применить толком =)
Нашёл лаконичное решение через пагинатор.
8 июля 2011 г.
Настройка VDS под dseye.ru
Решил переехать на более производительный тариф и заодно записать все типовые шаги в настройке (постоянно что нибудь да забуду).
Описание краткое, просто чтобы не забыть.
Описание краткое, просто чтобы не забыть.
4 июля 2011 г.
Zend_Paginator + Cache (memcached)
Столкнулся с проблемой при попытке прикрутить нативное кеширование к пагинатору (DbTableSelect адаптер)
бутстрап (производим кеш и скармливаем пагинатору)
контроллер
По всем мануалам всё должно работать, но нет:
во первых ZFDebug показывает лишний коннект к БД перед запросом данных пагинатора
во вторых этот запрос не кешируется никогда
Долго гуглил и копал сорцы, но как то безуспешно =(
Нашёл пару багов, где у людей файловый кеш пагинатора не работал при включенном профилировании через фаербаг, но показалось что проблема не та.
Версия 1.11.0, но и на продакшене 1.11.3 тоже самое.
Сам кеш разумеется работает нормально, без проблем подцепился к метаданным DbTable, да и ручками много где используется =)
Как временно решение прикрутил ручками кеширование этого запроса по составному ключу из параметров.
бутстрап (производим кеш и скармливаем пагинатору)
Copy Source | Copy HTML
$backendOptions = array(
- 'servers' => array( array(
- 'host' => '127.0.0.1',
- 'port' => (APPLICATION_ENV == 'production') ? 12245 : 11211,
- 'persistent' => true,
- 'weight' => 1,
- 'timeout' => 10,
- 'retry_interval' => 15,
- 'status' => true,
- 'failure_callback' => null ) ) );
- $frontendOptions = array(
- 'lifetime' => 3600
- 'automatic_serialization' => true,
- 'caching' => (APPLICATION_ENV == 'production') ? true : true,
- 'cache_id_prefix' => 'dseyeUP_',
- 'ignore_user_abort' => true );
- $cache = Zend_Cache::factory(
- 'Core',
- 'Memcached',
- $frontendOptions,
- $backendOptions);
- Zend_Registry::set('upCoreMem', $cache);
- Zend_Paginator::setCache($cache);
контроллер
Copy Source | Copy HTML
$count = $this->_worlds->getPlayersCount($this->idW);
- $this->view->paginator = $paginator = $this->_players->listWorldPlayers($this->idW, $page, $count);
По всем мануалам всё должно работать, но нет:
во первых ZFDebug показывает лишний коннект к БД перед запросом данных пагинатора
во вторых этот запрос не кешируется никогда
Долго гуглил и копал сорцы, но как то безуспешно =(
Нашёл пару багов, где у людей файловый кеш пагинатора не работал при включенном профилировании через фаербаг, но показалось что проблема не та.
Версия 1.11.0, но и на продакшене 1.11.3 тоже самое.
Сам кеш разумеется работает нормально, без проблем подцепился к метаданным DbTable, да и ручками много где используется =)
Как временно решение прикрутил ручками кеширование этого запроса по составному ключу из параметров.
Скрытая фишечка хeлпера FormRadio
Случайно наткнулся в сорцах ZF на возможность задавать атрибуты лейбла у радиобатонов.
Делается посредством конкатенации строки "label_" к имени атрибута.
Например:
Делается посредством конкатенации строки "label_" к имени атрибута.
Например:
Copy Source | Copy HTML- $this->formRadio('filter_alliance_mod',
- isset($this->searchProp->filterAllianceMod) ? $this->searchProp->filterAllianceMod : 'only',
- array('label_class' => 'text-top'),
- array('only' => 'только', 'not' => 'исключая'),
- ' ');
Стандартный роутер ZF или "будь бдителен!"
В zf, как известно, существует стандартный роутер по имени "default". Но есть и возможность описывать свои "человекоподобные" урлы.
Итак:
Есть пачка роутеров с параметрами. Параметров много, в роутерах задаются дефолтные значения и регулярки для валидации. Казалось бы - в контроллере эти переменные проверять ненадо, ведь если человек дошёл до контроллера, значит все проверки роутера выполнились. И тут (ВНЕЗАПНО!) я вспоминаю про стандартный роутер, без всех этих проверок.
Само собой ничего критичного там нет, да и prepared state дают защиту от SQL inject, но возможность вывести сразу все данные на одной странице (пагинация с изменяемым количеством итемов на странице) тоже может доставить хлопот.
Собственно вопрос: можно ли как то запретить переходить по стандартному роутеру для действий, к которым прописан кастомный роутер?
Доку пролистал вдоль и поперёк. Что нарыл:
1.Можно убить стандартный роутер вообще (ну или заменить на заведомо левый). Но этот вариант заставляет писать роутеры для всех страниц
2.Можно в критичных действиях проверять ($this->getFrontController()->getRouter()->getCurrentRouteName() == 'default' ). Достаточно гибкое решение, но генерирует слишком много повторного кода.
3. Зашить предыдущую проверку в плагин фронт контроллера и сочинить конфиг (для определения критичных действий). Тут уже можно разгуляться, но всё равно это смотрится костылём.
Итак:
Есть пачка роутеров с параметрами. Параметров много, в роутерах задаются дефолтные значения и регулярки для валидации. Казалось бы - в контроллере эти переменные проверять ненадо, ведь если человек дошёл до контроллера, значит все проверки роутера выполнились. И тут (ВНЕЗАПНО!) я вспоминаю про стандартный роутер, без всех этих проверок.
Само собой ничего критичного там нет, да и prepared state дают защиту от SQL inject, но возможность вывести сразу все данные на одной странице (пагинация с изменяемым количеством итемов на странице) тоже может доставить хлопот.
Собственно вопрос: можно ли как то запретить переходить по стандартному роутеру для действий, к которым прописан кастомный роутер?
Доку пролистал вдоль и поперёк. Что нарыл:
1.Можно убить стандартный роутер вообще (ну или заменить на заведомо левый). Но этот вариант заставляет писать роутеры для всех страниц
2.Можно в критичных действиях проверять ($this->getFrontController()->getRouter()->getCurrentRouteName() == 'default' ). Достаточно гибкое решение, но генерирует слишком много повторного кода.
3. Зашить предыдущую проверку в плагин фронт контроллера и сочинить конфиг (для определения критичных действий). Тут уже можно разгуляться, но всё равно это смотрится костылём.
Подписаться на:
Сообщения (Atom)