• 01Jul

    при создании нового джанго проекта я всегда выделяю две папки apps – для моих апов и compat – для сторонних апов, к разработки которых я не имею никакого отношения. Идея в том, что эти апы всегда остаются неприкосновенными для меня, и единственной точкой расширения остаются сеттингсы и возможно доп параметры, при инклюде урлов.

    А представьте, что вы создаете апу с именем catalog, ее вы потом хотите выложить в общее пользования, и необходимо для нее сделать больше точек расширения. Структура такого апа может быть

    • catalog
      • urls.py
      • views.py
      • models.py
      • settings.py
      • tests.py

    для 4 первых файлов можно просто вконце файла добавить строку, которая станет универсальной точкой расширения. Например для views.py

    1. try:
    2.     from ex_catalog.views import *
    3. except ImportError:
    4.     pass

    таким образом, если кто-то будет использовать Вашу апу — точкой расширения будет дополнительная апа ex_catalog, в котором вы можете переопределить некоторый функции из view.py, и при этом ex_catalog не надо добавлять в список апов в настройках.

    А теперь главный вопрос этого поста. Почему так не делают?

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , ,

  • 22Jun


    Чем меньше рутины мы привносим в свою работу, тем больше она может приносить удовольствия.

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

    Я Вам расскажу про Fabric(На момент написания статьи 0.9.1 — бала последняя стабильная версия), наиболее подходящий для этого инструмент, который делает все описанное и даже больше через ssh.

    Про установку рассказывать особо нечего, pip отлично справляется с этим.

    В корень своего проекта я кладу fabfile.py, в этом файле и будут храниться все процедуры для работы с Fabric. Ниже приведу небольшой пример скрипта, который будет архивировать наш проект, заливать его на сервер и там разархивировать.

    1. from fabric.api import *
    2. env.hosts = ['oduvan@lyabah.com']
    3.  
    4. def deploy():
    5.     local('tar czf /tmp/my_project.tgz .')
    6.     put('/tmp/my_project.tgz', '/tmp/')
    7.     with cd('/home/oduvan/www/test_fab/'):
    8.         run('tar xzf /tmp/my_project.tgz')

    Если у Вас все получилось, а я очень надеюсь, что с этим хостом и именем пользователя ни у кого кроме меня получиться ничего не может (так что поменяйте свою строку конекта во второй строке), то вы можете увидеть что-то сильно напоминающее вот это:

    1. $ fab deploy
    2. [localhost] run: tar czf /tmp/my_project.tgz .
    3. Password for oduvan@lyabah.com:
    4. [oduvan@lyabah.com] put: /tmp/my_project.tgz -> /tmp/my_project.tgz
    5. [oduvan@lyabah.com] run: tar xzf /tmp/my_project.tgz
    6. [oduvan@lyabah.com] err: tar: ./fabfile.pyc: time stamp 2010-06-21 10:03:41 is 4.461083597 s in the future
    7. [oduvan@lyabah.com] err: tar: .: time stamp 2010-06-21 10:03:41 is 4.460804762 s in the future
    8.  
    9. Done.
    10. Disconnecting from lyabah.com… done.

    Само собой, пароль у вас спросят и его необходимо будет ввести, в конце статьи я выложу свой пароль к ссш, чтоб вы могли протестить работу.

    Кому лень вводить пароли могу добавить после второй сроки
    env.password = ‘oh_its_my_real_password’

    либо сгенерить себе файл с ссш ключом и путь к нему положить в
    env.key_filename — в отличие и пароля тут может быть передан массив ключей

    Но и этот код можно сократить. У Fabric есть contrib libs, одна из них project. Тут подробно каждую я описывать не буду, просто покажу пример с одной из них, дабы просто показать, что они есть

    1. from fabric.api import *
    2. from fabric.contrib.project import rsync_project
    3. env.hosts = ['oduvan@lyabah.com']
    4.  
    5. def deploy():
    6.     local('python manage.py test', capture=False)
    7.     rsync_project('/home/oduvan/www/test_fab/','.')

    как видите наш код сократился до одной команды, не считая команду для тестирования Django проекта, ведь если какая-то команда возвратит ошибочный статус, то выполнения прекратится, а значит если тесты не проходят загрузка не начинается. Дополнительный параметр capture говорит о том, что необходимо скрывать выходные данные команды, мы эту опцию отключаем.

    Вот основные команды, которые Вам необходимо знать, чтоб свободно пользоваться Fabric

    put — копировать файл с локальной машины на удаленную. Доп параметр mode — устанавливает права на файл, см chmod
    get — копировать файл с удаленной на локальную
    local — выполнить команду на локальной машине. Доп параметр capture — скрывать выходные данные, по умолчанию False
    run — выполнить команду на удаленной машине
    sudo — выполнить команду на удаленной машине через судо. Доп параметр user — указываем имя пользователя, под которым необходимо запустить команду

    Обратите внимание, что у нас есть команда sudo, а значит при необходимости, мы можем и сервак зарелоадить и вообще сделать любые админ вещи, главное, чтоб пользователь был в судоерсах.

    Для деплойтинга на несколько серверов, причем различной конфигурации, и роли – у Fabric тоже кое-что припасено.

    1. from fabric.api import *
    2. from fabric.contrib.project import rsync_project
    3. env.roledefs =  {'web':['oduvan@lyabah.com','oduvan@dev.lyabah.com'],
    4.         'db':['oduvan@db1.lyabah.com','oduvan@db2.lyabah.com'],
    5.         'media':['oduvan@media@lyabah.com'],
    6.         }
    7.  
    8. @roles('web')
    9. def deploy():
    10.     rsync_project('/home/oduvan/www/test_fab/','.')

    в этом примере заливка файлов будет идти сразу на 2 вебовых сервака. Как видите вы можете запланировать у себя роли отдельных серверов под БД, под медиа файл и т.д.

    кроме как декоратаром роль можно указывать и при запуске процедуры

    1. $ fab deploy -R web

    Иногда в момент или во время запуска необходимо передать данные скрипту.

    В момент запуска это делается через аргументы самой функции

    к примеру если у вас

    1. def deploy(arg1,arg2):
    2.     pass

    то эти 2 аргумента можно передать как

    1. $fab deploy:'HI','HO'
    2. $ fab deploy:'HI',arg2='HO'
    3. $ fab deploy:arg1='HI',arg2='HO'

    Либо спросить что-то во время работы функции у пользователя функцией
    prompt(text, key=None, default=”, validate=None)

    Задает вопрос пользователю с текстом text, если пользователь не вводит данные, то возвращает значение из default, предварительно отчищая его функцией validate, и возвращает как результат этой функции, если не передан key, иначе кладет значение в env[key]

    А теперь примеры функций деплойтинга из реальной жизни, которые вы можете написать и у себя в проекте:

    bounce_wsgi_procs — зарелоадить wsgi через touch в него
    deploy_media — загружаем только медиа файлы
    migrate — запускаем скрипт миграции через South
    update_repositories – обновляем репозитарии
    update_dependencies — устанавливаем зависимости
    reload_nginx — перегружаем nginx
    deploy — полная установка, последовательный запуск всех этих функций.

    Подводя итоги могу сказать, что Fabric должна стать musthave tool в разработке.

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , , ,

  • 09May

    Думаю съездить на DevConf, который пройдет в Москве 17ого числа.

    Программа, как мне кажется, будет интересная. Не обойдут стороной нашу любимую Джангу. Да и дополнятся она еще будет. Не может не радовать обилие кофебрейков и перерывов, это на всех питонячих конфах такое?

    Интервью Ивана Салагаева о конфе о питоне и не только.

    А вы что думаете? Стоит слетать в Россию?

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , ,

  • 05May

    Мда. Экономней надо кодить. Мой эклипс с pydev и аптаной на борту не кисло оперотивочки съедает, а это, с появлением в моей семье нового нетбучного малыша – стало большой проблемой. И начал я посматривать в сторону VIMа. Не очень хочется прощаться с приятными IDE-шными фичами.

    Вот то, что у меня получилось, после того, как я досмерти замучал глупыми вопросами весь pythonua@conference.jabber.ru

    Тут у нас слева по F5 мы видим все функции и классы открытого файла, а по F6 файловый менеджер.

    Вот архив с моими настройками и плагиными vim.zip. Тем, у кого вим вообще никак не настроен – можно просто взять и распоказать это в свой хоум.

    Так что начинаю потихоньку прывыкать к виму. Думаю по мере развития этого моего нового пристрастия – буду вам писать.

    Ну и на последок несколько ссылок в тему.

    Статья на тему интеграции питона и вима. Хоть и старая но еще вполне актуальна. Да и вообще этот блог про вим очень хорош. На нем же наткнулся на подборочку команд для работы с вимом. Ну а кому показалось, что это банальная и маленькая подборочка – вот эта вам разорвет мозг.

    Спасибо deepwalker за помощь и пояснения и за львиную часть его конфига вима :)

    PS: А еще есть GVIM тоже, только в окошке и с менюшками.

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , ,

  • 31Jan

    pycamp-logo-newСегодня рано утром вернулся с pycamp, который прошел в Киеве 30ого января в учебном центре i-klass.

    Организаторы сказали, что это их первая попытка организовывать подобные мероприятия, и как по мне — у них для первого раза получилось довольно не плохо, правда розеток было мало, поэтому моя 17ти дюймовая малютка держалась на аккумуляторах.

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

    Александр Шигин (гость из солнечного Рамблера) «Почему Python — тормоз и как заставить его меньше тормозить». Были небольшие обзорчики кода, со сравнениями производительности. Сравнение результатов работы алгоритмов, реализованные разными способами — картежи, дикты, классы. Первые быстрее, но мы и так это знали. Хотя местами были довольно интересные результаты. Был упомянут Cython, но только вскользь, хотя мне бы тема была куда интереснее. Так что после в кулуарах мы написали небольшой хелло ворлд на cython, получили сошник и заюзали в самом питоне.

    Кратко выглядит примерно так

    ваш скрипт

    1. print "Hello World"

    скрипт setup.py:

    1. from distutils.core import setup
    2. from distutils.extension import Extension
    3. from Cython.Distutils import build_ext
    4.  
    5. setup(
    6.     cmdclass = {'build_ext': build_ext},
    7.     ext_modules = [Extension("helloworld", ["helloworld.pyx"])]
    8. )

    получаем сошник

    1. $ python setup.py build_ext –inplace

    и дальше его используем в ваших скриптах.

    1. >>> import helloworld
    2. Hello World

    Но также не забываем, что у него есть ограничение, т.е. не любой питонячий код вы можете откомпилить – генераторы, вложенные функции, локалсы, глобалсы вы юзать не можете и небольшие ограничения в определениях классов.

    Для себя отметил, что им как раз можно пользоваться для оптимизации питонячего кода практически без ограничений в использовании приятного синтаксиса питона. У себя в бложке буду освежать свои успехи в этом деле.

    Юрий Юревич «Рецепты декораторов». Лично для себя ничего нового не увидел, кроме того, что довольно грамотно все разложено по полочкам и что несомненно помогло упорядочить в голове знания.

    Михаил Кашкин (замляк из Днепра) «Работа с хранилищами данных в Google App Engine, отличия от реляционной модели». Я Апсы еще не юзал вообще. Но в скором времени мне таки придется уткнуть свой нос у туда. И пока то, что я узнал — мне не очень понравилось. Реляционных БД там нет вообще. Только их не реляционная БД и мемкеш.

    Мое первое впечатление — это модели бд, как в классической ОРМ, при этом кладутся данные в виде модели и в виде этой же модели забираются, с вытекающими ограничениями. Фишка которая сразу смутила весь зал — если вы копили-копили данные, а потом захотели добавить еще одно поле в модель, то старые данные, построенные на старой модели не обновятся, а нужно руками доставать каждого и задавать ему новое поле, и по словам Михаила — чем больше вы делаете выборку, тем дольше она получается.

    В кулуарах мне рассказали немного больше о самом App Engine. Он не совсем на шару, а в нем есть лимиты, я пологаю, что лимиты на все. Причем при приодалении этих лимитов вам просто закрывают доступ к сайту, хотя по совести их просто надо не давать использовать больше. И хотя питон с джангой были первыми в арсенале App Engine – они там со своими ограничениями. Так что 40 минут доклада оставило для меня много вопросов.

    Александр Соловьев. «Redis: Дикий Запад баз данных». Если коротко — то Redis — этот мемкешед, который сторит данные на винте с промежуточным хранилищем в памяти. С типами данными не только строки но и инты, листы, сеты. И с довольно обширным функционалом для их применения. Мастер-Слейв репликация, кстати только в этом наверно редис проигрывает мемкешу, т.к. мемкеш может использовать несколько серверов и данные между ними отлично распределять ( но редис держит данные на винте а не в памяти ). Ну и конечно же, Александр, как авторитетный велосипедист не мог не написать к редису чего-то своего pyredis ( питонячий клиент для редиса )

    Не мог не оценить подачу материала Александром. Очень живо, я даже подумал что презентация получилась в стиле теле-магазина: «Вы хитите это — пожалуйсто — редис отлично с этим справляется, это – и это вы можете сделать как 2 пальца об асфальт и то и то…». Но я бы на его месте такой продукт подавал как Стив Джобс — Макбук Аир. «Представте систему, которая быстрее мемкеша но данные сторит на винте, с типизацией ячеек и т.д. и т.п. И в конце Редис» Ну что-то в этом стиле.

    В любом случае, Александру спасибо. Будем смотреть, будем пробовать. Интересно, он кешовый бекенд для редиса на джанге уже написал?

    Владимир Пузанов и Владимир Кирилов «Расширения и встраивание Python». Эти два молодых хакера рассказали о том где можно применять питон, с чем и как его можно связывать. Jython, IronPython и многое другое, что я еще не запомнил. Надеюсь где нить раздобыть их презентацию. Но для себя отложил Stackless Python — у него очень «крутые» треды, на сколько крутые — я уже буду пробовать ручками сам. И когда я говорю о Stackless мне уже какой раз предлогают глянуть на greenlet. Общее впечатление о докладе осталось очень хорошее – хороший обзор, живая подача материал и оставило много вопросов (как и должно быть в подобных докладах). В конце парни показали прикольный примерчик как они питоном хачат сафари и меняют в нем титл через его жсный движок. Хотелось бы ответить всем бегающим по залу участникам с вопросам «Нафига надо было хачить софари». Объясняю — просто так!!! Просто точка ( довольно прикольная ) в докладе о расширениях и встраиваниях питона, обидно, что многие из всего доклада запомнили только эту точку.

    Андрей Мишковски «Использование Python в ГИС» . Проблематика Гиографические Информационные Системы для меня была нова, но подача информации была доступна и понятна даже слушателю не знакомым с темой. Так что если кто хочет может просмотреть презентацию, и дождаться выхода видео.

    Сергей Кирилов. «WebSockets в twisted». WebSockets — это новое расширение протокола HTTP в сторону двухстороннего взаимодействия клиент-сервер с одним коннектом, которая описана в стандарте HTML5. Поддерживается пока не всеми ( поэтому пользуемся библиотечкой, которая подменяет стандарт для тех, кто его еще не поддерживает ). Я мог пропустить, но по моему twisted-у был отведен один слайд, на котором выведено 42 строчки кода и сказано, что их 42 :) Кстати нагугли и хабровскую статью на эту тему.

    Не могу не оценить рисковый ход Сергея — реальная демонстрация продукта. Заработало почти с первого раза. У меня так никогда не получалось. Простенький чатик с инпутом и кнопочкой сабмит — впечатлил всех но не демострацией работы а то что почти все, у кого был ноут и получалось воспользоваться вайфаем — начали болтать и прикалываться друг с другом на большом экране, да так что в зале поднялся шум и гам, было очень весело, но по-моему не все успели задать вопросы.

    Сергей, если у вас сохранилась копия этой болтавни в чате — выложите куда-то, было прикольно :)

    И последний из понравившихся мне докладов был у Ивана Моргуна, сразу после нее я и убежал, т.к. надо было успеть на поезд обратно. Доклад был о «Работа с платежными системами в Django (PayPal, WebMoney)». Из джанго я ничего интересно для себя не вынес, но некоторые интересные моменты для PayPal подчеркнул.

    Организаторам, спонсорам и докладчикам мероприятия огромное спасибо. У вас все отлично получилось. Давайте как нить повторим. :)

    Еще о pycamp:
    curvedbrain.org “Мысли по мотивам PyCamp Kyiv”
    Макс Ищенко “мысли к вчерашнему pycamp”
    Vladimir PyCamp впечатления
    Дмитрий Гайворонский “PyCamp @ Kiev, 30 Jan 2010″
    … пишите в комментах ссылки на свои посты о кемпе …

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , ,

  • 20Jan

    c81822b789f2Так что через неделю собираюсь в Киев на PyCamp Kyiv. Все об этом мироприятии можно почтить у них на сайте.

    Кто не сможет там быть – обещаю выложить небольшую статейку о том, что вы пропустили ( и углубляясь в те моменты, которые мне были интересны )

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , ,

  • 11Dec

    ai_bolit

    Всем привет. Да, знаю, я давно не писал. Ну простите, и как это не банально, был занят. А заставила меня написать одна мысля. И пожалуйста, дочитайте это до конца, потому что или это очень круто или я опять что то не понимаю, и с температурой 38 мне лучше за клаву не садиться.

    Кеш. Я им пользуюсь для того, чтобы данные, которые я долго вычисляю — положить в память куда нить, чтоб если они понадобились — быстро их оттуда взять. Ну а если их там нет, то просто пересчитать и положить. Если вы им пользуетесь также, то читайте дальше иначе напишите комментарий, который начнется со слов: «Тю, блин, а я его совершенно по другому юзаю, глянь…»

    Т.е. на сетах и гетах все сводится к примерно следующему алгоритму.

    1. from django.core.cache import cache
    2.  
    3. def setter(key,l_value,timeout=0):
    4.     val = cache.get(key)
    5.     if val is None:
    6.         val = l_value()
    7.         cache.set(key,val,timeout)
    8.     return val

    где l_value — это ссылка на функцию, значение которой будет получено, в случае если его нет в кеше.

    Вот этот умопомрачительный алгоритм у меня лежит в основе кеширования.

    Хух… если у вас также, то идете дальше. Надеюсь сейчас осталось достаточно народу.

    Прогуливаясь легкой и непринужденной походкой по блогосфере рунете я уже в который раз натыкаюсь на довольно странное решение следующей проблемы.

    Если есть какие либо данные которые системе нужны часто, но вычисляются долго, то их прямое получение по алгоритму, описанному выше — просто убивает систему. Потому что как только они пропадают из кеша — все, кому нужны эти данные — начинают скопом — все вместе их получать. Например статистика по пользователям у вас вычисляется 5 сек, а выводится на главной странице, с посещаемостью 50 чел в сек, значит одновременно эти данные будут получать 250 процессов – что, может привести к смерти.

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

    Тут просто тьма тьмущая узких мест

    1.Старт у системы должен быть особый. Т.е. в нулевой точке в кеше уже должны быть часто доступные данные.
    2.У вас двойные данные в кеше, т.е. две копии, а ведь часто бывает и такое, что трудновычисляемые данные — это и большие данные.
    3.И последнее — если процесс, который вычисляет заекспаревшиеся данные — умирает. То умирают все. Явно теряем в отказоустойчивости.

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

    Если в ячейку с ключем класть не данные, а хеш из двух значений — данные, и время, когда их надо обновить. (ТАДАМ избавились от второго пункта)

    А что если ты перед началом вычислений будеш класть в другой системый и уникальный ключ в кеше время, когда первый, начавший вычисления – планирует их закончить. А остольные процессы, которые захотят получить данные и не увидят их — смогут орентироваться на системный ключь, чтоб понимать, что данные скоро будут и их необходимо подождать или мы не дождались и попробуем еще раз. (ТАДАМ избавились от первого и третьего)

    А теперь скучный код. Чтоб легче было читать — его необходимо скрестить с алгоритмом, который я описывал выше. И если функция гет — вернет None то эти данные сразу начнут вычисляться.

    Небольшой рандом необходим, чтоб все процессы сразу не набросились вычислять после первого сдавшегося, а нарастающий таймаут необходим для быстрого избавления от быстрых данные и размеренного ожидания долгих.

    1. from django.core.cache.backends.memcached import CacheClass as BaseCacheClass
    2. from datetime import datetime,timedelta
    3. from time import sleep
    4. from random import random
    5.  
    6. ADDITION_EXP_TIME = 20
    7. TIME_FOR_CREATE = 5
    8.  
    9. class CacheClass(BaseCacheClass):
    10.     def add(self, key, value, timeout=0):
    11.         timeout = timeout or self.default_timeout
    12.         value = {'v':value,'e':datetime.now()+timedelta(seconds=timeout)}
    13.         super(CacheClass,self).add(key,value,timeout+ADDITION_EXP_TIME)
    14.        
    15.     def set(self, key, value, timeout=0):
    16.         timeout = timeout or self.default_timeout
    17.         value = {'v':value,'e':datetime.now()+timedelta(seconds=timeout)}
    18.         super(CacheClass,self).set(key,value,timeout+ADDITION_EXP_TIME)
    19.    
    20.     def get(self,key, default=None):
    21.         wait_next_val = 0
    22.         while True:
    23.             wait_next_val += 0.1
    24.             value = super(CacheClass,self).get(key,default)
    25.             now = datetime.now()
    26.            
    27.             if value is not None and now<value['e']:
    28.                 return value['v']
    29.            
    30.             wait_system_key = 'wait_system__%s__wait_system'%key
    31.             wait_system = super(CacheClass,self).get(wait_system_key)
    32.            
    33.             # if you find expired key first or you don't wait the next person
    34.             if wait_system is None or wait_system<now:
    35.                 super(CacheClass,self).set(wait_system_key,datetime.now()+timedelta(seconds=TIME_FOR_CREATE),TIME_FOR_CREATE + 5)
    36.                 return None
    37.            
    38.             #if somebody already getting a new value
    39.             if value is not None:
    40.                 return value['v']
    41.            
    42.             sleep(random()*wait_next_val)

    И на всякий случай. Если вы все таки считаете это отличной идее. Кладем это в файлик с незамысловатым названием smart_cache.py рядом с settings.py, а в settings.py записываем

    1. CACHE_BACKEND = "smart_cache://127.0.0.1:11211"
    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , ,

  • 15Oct

    Идея в том, что мы делаем дамп объекта cPickle и сохраняем его в нем же. А после, чтоб узнать, изменился ли объект – делаем его дамп еще раз и проверяем результаты. Так что кода строчек 5

    вот что у меня получилось:

    1. from cPickle import dumps
    2.  
    3. #base class for monitoring changes
    4. class ChangesMonitor:
    5.     _cm_last_dump = None
    6.     def is_chaged(self):
    7.         prev_dump = self._cm_last_dump
    8.         self._cm_last_dump = None
    9.         cur_dump = dumps(self, -1)
    10.         self._cm_last_dump = cur_dump
    11.         return ( ( prev_dump is not None ) and ( prev_dump != cur_dump ) )
    12.        
    13. if __name__ == '__main__':
    14.     print 'Test Example'    
    15.    
    16.     #mix monitoring class with your common class
    17.     class MyGreateObject(ChangesMonitor,object):
    18.         one_val = 5
    19.         second_val = 7
    20.         def some_changes(self):
    21.             self.second_val += 5
    22.    
    23.     #and testing
    24.     my_obj = MyGreateObject()
    25.     print my_obj.is_chaged()
    26.     print my_obj.is_chaged()
    27.     my_obj.some_changes()
    28.     print my_obj.is_chaged()
    29.     print my_obj.is_chaged()
    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , ,

  • 01Oct

    Я уже посягал на суверинитет джанги. Но это было давно и не правда. Более того, меня тогда убедили, что делаю я глупости, и я даже убедился сам, в последствии, что на самом деле делаю глупости. Но мысть о том, что urls.py не нужен – не перестает меня беспакоить. Поэтому очередно фин, аморальный бред – называйте как хотите, но мне безумно нравится.

    Идея проста. Вьюха и урла всегда вместе – а значит одно должно быть декоратаром для другого.

    Итак главный urls.py имеет обычный вид

    1. from django.conf.urls.defaults import *
    2.  
    3. urlpatterns = patterns('',
    4.     (r'^someurl/',include('someapp.url_view')),
    5. )

    /someapp/url_view.py – тут у нас сбстно и хранятся вьюхи с урлами. Как видите, декоратор tourl нам земенил запись в urls.py

    1. from django.http import HttpResponse
    2. from tourl import tourl
    3.  
    4. @tourl(r'^and/$')
    5. def and_(request):
    6.     return HttpResponse('and')
    7.  
    8. @tourl(r'^gg/$')
    9. def index(request):
    10.     return HttpResponse('OK')

    /someapp/tourl.py – ну и код самого декоратора

    1. from django.conf.urls.defaults import *
    2. import sys
    3. import functools
    4. def tourl(url_patern,*args,**kwargs):
    5.     def paramed_decorator(func):
    6.         @functools.wraps(func)
    7.         def decorated(self):
    8.             return func(self)
    9.         module =sys.modules[func.__module__]
    10.        
    11.         if not hasattr(module, 'urlpatterns'):
    12.             module.urlpatterns = patterns('',)
    13.              
    14.         module.urlpatterns   += patterns('',
    15.             url(url_patern,decorated,*args,**kwargs),
    16.         )
    17.         return decorated
    18.     return paramed_decorator

    Помоему и симпотично и по производительности не бьет. Вобщем конфетка! Что скажите?

    PS: Добавил снипет.

    PSS: В снипетсах посоветовали добавить functools.wraps

    PSS: А еще можно использовать и так

    1. from django.http import HttpResponse
    2. from tourl import tourl, patterns,url
    3.  
    4.  
    5.  
    6. @tourl(r'^and/$')
    7. def and_(request):
    8.     return HttpResponse('and')
    9.  
    10.  
    11. def index(request):
    12.     return HttpResponse('OK')
    13.  
    14. tourl(r'^gg/$')(index)
    15.  
    16.  
    17. def ordinary(request):
    18.     return HttpResponse('Ordinary')
    19.  
    20. urlpatterns += patterns('',
    21.             url(r'^ord/$',ordinary)
    22.         )
    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , , , ,

  • 13Sep

    Развел небольшой холивар на своем любимом блоге.

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , ,

« Previous Entries   

Recent Posts

Recent Comments

  • Я просто оставлю это тут: ...
  • спасибо...
  • Если вдуматься в каждое слово, то время беСконечно в русском...
  • Спасибо, Евгений, исправленно.P.S.: перехал на диску...
  • за опечатку - спасибо...