Иногда бывает необходимость посмотреть локальные переменные функции в python, которая вызвала Exception в самом верху стека вызовов.
Проще всего сделать это, воспользовавшись штатным модулем inspect внутри блока except:
inspect.trace()[-1][0].f_locals
Показаны сообщения с ярлыком python. Показать все сообщения
Показаны сообщения с ярлыком python. Показать все сообщения
пятница, 24 января 2014 г.
вторник, 6 ноября 2012 г.
Трекинг страниц в Google Analytics на серверной стороне
Для недавно сделанного мной микросервиса shares.datagreed.ru мне захотелось отслеживать переходы по разным адресам api. Как это сделать, если Google Analytics интегрируетсяв страницу посредством JS?
Я тоже не знал. Поиск привел меня к официальной библиотеке на PHP для мобильных сайтов, на которых предполагалось не использовать яваскрипт.
Дальнейшие мои изыскания вылились в небольшую библиотеку для питона, которая позволяет использовать GA со стороны сервера. Штатно в библиотеку влючены классы для Django и Flask. Класс для Flask в данный момент развернут и полностью функционирует у меня на shares.datagreed.ru, класс для Django я пока что не тестировал.
Проект живет на здесь, в моем битбакете.
Я тоже не знал. Поиск привел меня к официальной библиотеке на PHP для мобильных сайтов, на которых предполагалось не использовать яваскрипт.
Дальнейшие мои изыскания вылились в небольшую библиотеку для питона, которая позволяет использовать GA со стороны сервера. Штатно в библиотеку влючены классы для Django и Flask. Класс для Flask в данный момент развернут и полностью функционирует у меня на shares.datagreed.ru, класс для Django я пока что не тестировал.
Проект живет на здесь, в моем битбакете.
понедельник, 13 августа 2012 г.
Django на uWSGI и nginx
Старые способы запуска сервера, которыми я пользовался обычно, не предполагали, что на сервере больше одного приложения, да и в принципе сейчас уже несколько архаичны. В свете того, что Django с версии 1.4 официально перешла на WSGI, я решил набросать небольшой гайд по разворачиванию приложения на связке nginx+uWSGI.
среда, 8 августа 2012 г.
virtualenv wrapper - удобная обертка над virtualenv
Что такое virtualenv никакому разработчику на python и рассказывать не нужно, но не все знают (или это только я как-то пропустил), что есть удобная обертка над ним, позволяющая производить все операции с виртуальным окружением гораздо быстрее. Называется соответственно - virtualenv wrapper.
Ставится, как обычно, через pip:
$ pip install virtualenvwrapper
После установки нужно сделать пару манипуляций для его конфигурирования.
Ставится, как обычно, через pip:
$ pip install virtualenvwrapper
После установки нужно сделать пару манипуляций для его конфигурирования.
Декоратор для автоматической регистрации сигналов Django
Давно наткнулся в сети на хороший сниппет, позволяющий декоратором навесить сигнал сохранения модели на метод класса модели Django. Уже и не помню, где его нашел, поэтому просто приведу чуть-чуть доработанный мной сниппет:
Пользоваться декоратором просто. Создаете модель, в ней делаете методы pre_save_handler и/или post_save_handler и оборачиваете класс декоратором:
Вот и все. pre_save_handler и post_save_handler сами вызовуться по соответствующим сигналам сохранения модели.
from functools import wraps from django.db.models.signals import pre_save from django.db.models.signals import post_save def autoconnect_signals(cls): """ Class decorator that automatically connects pre_save/post_save signals on a model class to its pre_save_handler()/post_save_handler() methods. """ def connect(signal, func): cls.func = staticmethod(func) @wraps(func) def wrapper(sender, *args, **kwargs): return func(kwargs.get('instance'), args, kwargs) signal.connect(wrapper, sender=cls) return wrapper if hasattr(cls, 'pre_save_handler'): cls.pre_save_handler = connect(pre_save, cls.pre_save_handler) if hasattr(cls, 'post_save_handler'): cls.post_save_handler = connect(post_save, cls.post_save_handler) return cls
Пользоваться декоратором просто. Создаете модель, в ней делаете методы pre_save_handler и/или post_save_handler и оборачиваете класс декоратором:
@autoconnect_signals class Book(models.Model): #... name = models.SlugField(_("Name"), max_length = 150, unique = True) def pre_save_handler(self,*args, **kwargs): u"""Сигнал, получаемый перед сохранением модели.""" print self.name #в self передается сам инстанс модели. #Остальное есть в аргументах. def post_save_handler(self,*args, **kwargs): u"""Сигнал, получаемый после сохранения модели.""" print self.name
Вот и все. pre_save_handler и post_save_handler сами вызовуться по соответствующим сигналам сохранения модели.
пятница, 27 июля 2012 г.
Docstring coverage - покрытие python-кода документацией
Как проверить, что python-разработчики хорошо задокументировали код, кроме как просматривать все руками или генерировать pydoc'ом документацию и сравнивать с исходниками? Вот и я не нашел никакого решения, пока случайно не натолкнулся на старый-престарый скрипт, который вдохновил меня на форк и последующую доработку.
В результате у меня получился полезный инструмент Docstring coverage, позволяющий оценить процентное покрытие кода документацией по всему проекту.
Пускается так:
docstring-coverage [опции] <путь к папке или модулю>
Среди опций есть -m, которая заставляет утилиту пропускать __магические__ методы python и -v, позволяющая настроить уровень "болтливости" вывода от 0 до 3.
Можно импортировать в рабочий проект использовать для получения статистики по покрытию:
import docstringcoverage
cover_results = docstringcoverage.get_docstring_coverage('somefolder/somefile.py')
Вся документация с примерами есть на странице проекта.
В результате у меня получился полезный инструмент Docstring coverage, позволяющий оценить процентное покрытие кода документацией по всему проекту.
Пускается так:
docstring-coverage [опции] <путь к папке или модулю>
Среди опций есть -m, которая заставляет утилиту пропускать __магические__ методы python и -v, позволяющая настроить уровень "болтливости" вывода от 0 до 3.
Можно импортировать в рабочий проект использовать для получения статистики по покрытию:
import docstringcoverage
cover_results = docstringcoverage.get_docstring_coverage('somefolder/somefile.py')
Вся документация с примерами есть на странице проекта.
среда, 18 июля 2012 г.
django-paramfield
Решил выложить в паблик поле ParamField для Django, которое изначально использовалось мной в одном старом проекте, который, к сожалению, канул в лету из-за недостатка финансирования. Но поле достаточно полезное и используется мной сейчас в других проектах на Django.
Исходники и документацию можно взять в на странице проекта в bitbucket.
Расскажу вкратце об этом поле.
Исходники и документацию можно взять в на странице проекта в bitbucket.
Расскажу вкратце об этом поле.
среда, 27 июня 2012 г.
Установка psycopg2 на OSX Server
По долгу службы понадобилось установить psycopg2 для работы с PostgreSQL под OSX. Задача оказалась нетривальной.
Если вкратце, то ставить его нужно так:
PATH=$PATH:/Library/PostgresPlus/9.1/bin/ sudo easy_install psycopg2
После чего поправить симлинки на libssl и libcrypto (если их версии ниже 1.0.0, что скорее всего так), иначе psycopg при импорте будет выпадать с ошибкой:
sudo ln -f /Library/PostgreSQL/9.1/lib/libcrypto.1.0.0.dylib /usr/lib/libcrypto.dylib
Если вкратце, то ставить его нужно так:
PATH=$PATH:/Library/PostgresPlus/9.1/bin/ sudo easy_install psycopg2
После чего поправить симлинки на libssl и libcrypto (если их версии ниже 1.0.0, что скорее всего так), иначе psycopg при импорте будет выпадать с ошибкой:
sudo ln -f /Library/PostgreSQL/9.1/lib/libcrypto.1.0.0.dylib /usr/lib/libcrypto.dylib
sudo ln -f /Library/PostgreSQL/9.1/lib/libssl.1.0.0.dylib /usr/lib/libssl.dylib
И вот теперь, наконец, psycopg2 будет нормально импортироваться.
понедельник, 2 января 2012 г.
Шаблон для геттера кешируемой переменной в Django
Когда пишешь под Django, часто приходится писать геттеры каких-то переменных модели, которые в первый раз извлекаются из базы данных, а потом сохраняются в приватном свойстве объекта (похожим образом работает стандартный джанговский LazyUser из AuthenticationMiddleware, например). Решил поделиться своим шаблоном для этого случая, который подойдет для PyDev или любого другого редактора, основанного на Eclipse:
def ${method_name}(self, try_cached = True, save_cache = True):
result = None
if try_cached:
#если разрешено отдавать из кеша, отдаем
if hasattr(self, '_cached_${method_name}'):
return self._cached_${method_name}
${cursor}
if save_cache:
#если надо закешировать в объекте, сохраним в приватном свойстве
self._cached_${method_name} = result
return result
среда, 4 мая 2011 г.
Отправка писем с DKIM-подписью в Django
Если вы вдруг обеспокоились тем, чтобы ваши письма не попадали в черные списки почтовых сервисов и решили-таки прикрутить DKIM-подписи к своим письмам в Django, то нет ничего проще.
Начиная с версии 1.2, Django стала поддерживать почтовые backend'ы, что существенно облегчило жизнь разработчику в этом плане. Все, что требуется, так это установить pydkim и создать модуль с бекендом, например <ваше_приложение>/mail/backends.py:
Останется только сменить в settings.py параметр EMAIL_BACKEND на "<ваше_приложение>.mail.backends.DKIMBackend" и прописать там же DKIM_SELECTOR, DKIM_DOMAIN и DKIM_PRIVATE_KEY (смотрите докстринг в коде). Сгенерировать недостающие ключи можно тут.
Начиная с версии 1.2, Django стала поддерживать почтовые backend'ы, что существенно облегчило жизнь разработчику в этом плане. Все, что требуется, так это установить pydkim и создать модуль с бекендом, например <ваше_приложение>/mail/backends.py:
from django.core.mail.backends.smtp import EmailBackend from django.conf import settings import dkim class DKIMBackend(EmailBackend): u''' Бекенд, позволяющий вставлять в письма DKIM-подпись. Требует определения переменных в settings: DKIM_SELECTOR - селектор, все что до точки в "selector._domainkey.example.com" DKIM_DOMAIN - домен например, "example.com" DKIM_PRIVATE_KEY - приватный DKIM-ключ. Полностью, включая "-----BEGIN RSA PRIVATE KEY-----" и т.п. @requires: python-dkim, есть на http://hewgill.com/pydkim ''' def _send(self, email_message): if not email_message.recipients(): return False try: message_string = email_message.message().as_string() signature = dkim.sign(message_string, settings.DKIM_SELECTOR, settings.DKIM_DOMAIN, settings.DKIM_PRIVATE_KEY) self.connection.sendmail(email_message.from_email, email_message.recipients(), signature+message_string) except: if not self.fail_silently: raise return False return True
Останется только сменить в settings.py параметр EMAIL_BACKEND на "<ваше_приложение>.mail.backends.DKIMBackend" и прописать там же DKIM_SELECTOR, DKIM_DOMAIN и DKIM_PRIVATE_KEY (смотрите докстринг в коде). Сгенерировать недостающие ключи можно тут.
понедельник, 11 апреля 2011 г.
Взвешенный выбор в Python
Очень часто встречаю людей, которые зачем-то пытаются сделать взвешенный выбор в питоне, создавая огромных размеров массивы с повторяющимися значениями и потом выбирая из них результат с помощью random.choice. Вариант, конечно, логичный и простой в реализации, но... как же он тормозит и сколько памяти расходует. Что если у меня у одного элемента вес 5000, а у другого 1? Зачем мне ради одной операции строить массив длинной в 5001 элемент? :)
Конечно же, есть варианты гораздо проще и изящнее. Списывайте:
Конечно же, есть варианты гораздо проще и изящнее. Списывайте:
import random def weighted_choice(choices): u''' Взвешенный псевдослучайный выбор. Чем выше вес, тем выше шанс выпадения значения. @param choices: список или кортеж пар вида: ( ('choice', 14), ('choice2', 11), ... (<значение>, <вес> ) ''' total = sum(w for c,w in choices) r = random.uniform(0, total) upto = 0 for c, w in choices: if upto+w > r: return c upto += w assert False, "Shouldn't get here"Работает вот так:
test_choices = ( ('Foo', 8), ('Bar', 3), ('god damn!', 1) ) for i in xrange(10): print weighted_choice(test_choices)
Подписаться на:
Сообщения (Atom)