Сегодня ночью мне пришло письмо от bitbucket, о том что не знакомый мне человек дает мне грант на запись в репозиторий. В названии репозитория доменное имя, по которому замещен интернет-магазин.
Грант, очевидно, был отозван сразу. Мне естественно, стало интересно посмотреть что там на сайте. Тему этого сайта для себя считаю закрытой, но какая-то более специализированная история, могла бы меня заинтересовать. Например, так можно раскручивать сервис непрерывной интеграции или аутсорс тестирования.
Для того что бы выдать грант пользователю достаточно знать его ФИ или username. Такие данные не сложно получить с помощью API bitbucket'а http://restbrowser.bitbucket.org/.
5 мар. 2015 г.
24 февр. 2015 г.
Timeout декоратор
Если функция будет работать долго, и при этом нужно чтобы она работала не дольше определенного количества секунд, можно применить такой вот декоратор:
import errno import os import signal from functools import wraps class TimeoutError(Exception): pass def timeout(seconds=10, error_message=os.strerror(errno.ETIME)): """ @timeout(60) def long_functions(): <your code here> """ def decorator(func): def _handle_timeout(signum, frame): raise TimeoutError(error_message) def wrapper(*args, **kwargs): signal.signal(signal.SIGALRM, _handle_timeout) signal.alarm(seconds) try: result = func(*args, **kwargs) finally: signal.alarm(0) return result return wraps(func)(wrapper) return decorator
Lock в файл или в redis?
Иногда нужно гарантировать эксклюзивное исполнение функции для определенного набора данных. Например, только одно одновременное изъятие данных из какого-либо источника. На помощь в таких ситуациях приходят локи.
Проще всего создать какой-нибудь lock-файл и проверять его существование. Если есть файл - lock включен.
Жалко напрягать HDD такими мелкими операциями. Попробуем делать lock в redis:
Теперь проверим какой вариант быстрей:
Результаты:
Lock в redis в 3 раза быстрей.
Проще всего создать какой-нибудь lock-файл и проверять его существование. Если есть файл - lock включен.
import os from contextlib import contextmanager class LockedException(Exception): pass @contextmanager def file_lock(lock_file): """ with file_lock('/tmp/file.lock'): some code here """ if os.path.exists(lock_file): raise LockedException('LockedException') else: open(lock_file, 'w').write("1") try: yield finally: os.remove(lock_file)
Жалко напрягать HDD такими мелкими операциями. Попробуем делать lock в redis:
import redis from contextlib import contextmanager r = r = redis.StrictRedis(host='localhost', port=6379, db=0) class LockedException(Exception): pass @contextmanager def redis_lock(lock_id): """ with redis_lock('unique_redis_key'): some code here """ if r.get(lock_id): raise LockedException('LockedException') else: r.set(lock_id, 1) try: yield finally: r.delete(lock_id)
Теперь проверим какой вариант быстрей:
if __name__ == '__main__': import time from numpy import mean count = 10000 times1 = [] for i in xrange(0, count): start = time.time() with file_lock('/tmp/file.lock'): pass times1.append(float(time.time() - start)) times2 = [] for i in xrange(0, count): start = time.time() with redis_lock('redis_lock'): pass times2.append(float(time.time() - start)) print 'file lock:', max(times1), min(times1), mean(times1) print 'redis lock:', max(times2), min(times2), mean(times2)
Результаты:
| max | min | avg | |
| file_lock | 0.0817749500275 | 0.000284910202026 | 0.000996773791313 |
| redis_lock | 0.00140619277954 | 0.000319957733154 | 0.000346991157532 |
Lock в redis в 3 раза быстрей.
12 янв. 2015 г.
Shiningpanda и jenkins
Надкусил собаку, при настройке CI на базе jenkins. Проглотить мешают постоянные всякие мелочи. Например из последнего: плагин Virtualenv Builder [Shiningpanda], с помощью которого можно более лучше развертывать виртуальные окружения python, принимает настройку "name". По документации, настройка соответствует названию virtualenv окружения. Изменение этой опции не влияет на фактическое название окружения (по факту получается что-то вроде c934fdf).
При всем этом, Shiningpanda реально экономит время при создании CI для python проекта.
Сборка:
[Virtualenv Builder]
pip install pytest pytest-cov
$PYTHON_EXE setup.py install
py.test --junitxml junit.xml --cov-report xml --cov src tests.py
Постсборка:
[Cobertura coverage]
coverage.xml
[juint]
result.xml
И далее в постсборке запускает выкатка библиотеки и/или обновление девелоперского-стейджа.
А как в ваших компаниях реализован CI?
При всем этом, Shiningpanda реально экономит время при создании CI для python проекта.
Сборка:
[Virtualenv Builder]
pip install pytest pytest-cov
$PYTHON_EXE setup.py install
py.test --junitxml junit.xml --cov-report xml --cov src tests.py
Постсборка:
[Cobertura coverage]
coverage.xml
[juint]
result.xml
И далее в постсборке запускает выкатка библиотеки и/или обновление девелоперского-стейджа.
А как в ваших компаниях реализован CI?
11 янв. 2015 г.
Отправка push-сообщений на мобильные устройства
Вчера меня в очередной раз спросили "как и чем лучше отправлять пуши?" Отвечаю: если у вас не очень много сообщений в месяц - идеально использовать http://urbanairship.com/. В нем есть много "богатой" аналитики прямо из коробки и он поможет вам акцентировать внимание на том, что действительно важно в этом вопрос: длинна сообщения, формат, скорость и гарантии доставки, отслеживания и аналитика. Есть бесплатный ознакомительный период, дающий максимум возможностей, но и бесплатной версии хватит, чтобы отправлять пуши на android, ios, win phone.
Если же количество отправляемых ежемесячно сообщений большое, а квартиру Москве продавать жалко - пишите свое решение, как поступили мы в Anews. В основе нашего решения django-push-notifications, который, в свою очередь, использовал код двух более низкоуровневых библиотек, которые постепенно были улучшены (без возврата кода в оные). Мы для себя улучшили поддержку юникода при отправке сообщений на iOS и добавили ttl в андройде (последние версии библиотеки ttl уже есть), обработку ответов о GCM сервера.
На данный момент на Anews мы почти ежедневно отправляем 500 тысяч сообщений, которые улетают к пользователям в среднем менее чем за 12 минут.
Блогинг на самописном джвике
В общем, эксперимент с блогом на самописном джвике можно считать завершенным. Больше всего этот опыт похож на попытку создать свою собственную почту вместо использования gmail - есть ощущение защищенности от Большого Брата, но нет тех печенек, которыми он заманивает на темную сторону.
Самая главная печенька, которой мне не хватало - отсев спам комментариев. Я натурально ловил себя на мысли, что не хочу заходить в админку блога, потому что там снова тонны скриптованных комментов с предложением сыграть в онлайн казино и сразу после этого медикаментозно увеличить себе пенис. Буэ.
После переноса постов из старого блога в новые прилетело сразу несколько комментов, которые я не получал к постам более года, потому как на том движке у меня не было старых подписчиков. Приятно получил комментарии к посту, но радость омрачает осознание того, что подписчики получили сразу пачку старых постов в RSS-ленте. Не удивительно, что общий тон комментариев раздраженно-осуждающий.
Самая главная печенька, которой мне не хватало - отсев спам комментариев. Я натурально ловил себя на мысли, что не хочу заходить в админку блога, потому что там снова тонны скриптованных комментов с предложением сыграть в онлайн казино и сразу после этого медикаментозно увеличить себе пенис. Буэ.
После переноса постов из старого блога в новые прилетело сразу несколько комментов, которые я не получал к постам более года, потому как на том движке у меня не было старых подписчиков. Приятно получил комментарии к посту, но радость омрачает осознание того, что подписчики получили сразу пачку старых постов в RSS-ленте. Не удивительно, что общий тон комментариев раздраженно-осуждающий.
10 янв. 2015 г.
Интервью на openmonte.com
Очень интересный для меня опыт - интервью для сайта openmonte.com. Опубликовано почти месяц назад, но до этого было как-то не до блога. Паааадписывайтесь, ставьте лайк и др. и пр.! Что там еще нужно писать в таких случая? )
Подписаться на:
Сообщения (Atom)