Архив метки: Python

aiohttp 0.14

Выпустил новую версию библиотеки.

Из вкусного — Web Sockets для aiohttp.web серверов, оптимизация скорости работы, множество мелких улучшений.

Полный список изменений — здесь.

Автор: Andrew Svetlov

Задачи оптимизации

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

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

Мы же, для примера, возьмем классическую задачу группового путешествия!)
Читать

Почему я не люблю Flask

Есть такой популярный microframework: Flask.

Многим нравится: легкий и простой для изучения, то да сё.

А мне — категорически нет.

Нелюбовь началась с элементарного: request — это thread local variable:

import flask
from myapp import app

@app.route(‘/’)
def handler():
req = flask.request
if ‘arg’ in req.args:
process_arg(req.args[‘arg’])
###

Т.е. для для того чтобы узнать с какими GET или POST параметрами вызвали мой код — я должен обращаться к глобальной переменной!

Я знаю разницу между global variable и thread local variable если что — но это не избавляет от неприятного послевкусия.

Ага, есть еще и flask.g!

Если уж мне потребуются context local variables — я их буду использовать по моему выбору, морщась от осознания собственного несовершенства. Зачем flask их мне навязывает?

Дальше — больше.

Смотрим еще раз:

from myapp import app

@app.route(‘/’)
def handler():
###

Имеем наполовину сконфигурированный импортированный откуда-то app, к которому добавляем обработчик.

Мне это не нравится. Я хочу сделать app и добавить в него route table.

Flask это позволяет, но документация провоцирует делать ровно наоборот.

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

Идем дальше.

Параметры в route:

@app.route('/user/')
def handler(username):
    pass

Весной это казалось мне удачным. Даже сделал что-то похожее в aiorest.

Потом понял, что штука абсолютно бесполезная: нам всегдатребовалось что-то из HTTP HEADERS, COOKIES и GET/POST parameres в обработчике запроста.

Чтобы проверить — авторизирован ли пользователь, например.

Выпилил.

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

route args, GET, POST, COOKIES — каждый dict может иметь перекрывающиеся имена-названия.

Паша Коломиец в zorro попытался решить проблему через аннотации:

def handler(self, request: Request):
    pass

Т.е. handler имеет параметр с аннотацией Request — он получит в него request object.

В zorro можно регистрировать свои аннотации для получения дополнительной информации.

Симпатично и элегантно — но слишком сложно для библиотеки для чайников.

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

Заключение

Я не призываю не использовать flask, у меня нет такой цели. Хотите граблей — получайте.

Просто сейчас я занялся добавлением в aiohttp WEB-сервера, пригодного для использования простым программистом.

И я точно знаю, чего не будет в aiohttpконтекстных переменныхи зависимостей на этапе импорта.

aiohttp.web должен быть прост насколько это возможно, но не проще.

Желающие выстрелить себе в ногу пусть делают это в библиотеках, построенных на основе aiohttp.web — мы дадим им такую возможность.

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

Автор: Andrew Svetlov

pep8 и 80 символов в строке

На самом деле 79 если внимательно читать pep 8, если что…

Посетил на днях Python Party, организованной компанией Yandex.
Мероприятие понравилось, а самый интерес был потом, на «поболталках» в кабаке.

Был на party доклад от Кирилла Борисова «Контроль за стилем кода». Интересный и толковый.

Только я возражаю против с высказывания вроде:
  — pep8 рекомендует ограничивать длину строк в 79 символов максимум. Мы с этим несогласны — сейчас мониторы большие, можно писать 120 символов и это великолепно помещается на экране.

Я везде строго пишу с ограничением на 79 символов.

Попробую объяснить почему.

1. Во первых сам код Python так написан и patch вылезающий за границы просто не будет принят. OK, я committer — значит тем более обязан следовать соглашениям.
2. Во вторых мой редактор (emacs если что) настроен на то чтобы подсвечивать длинные строки. И когда я открываю код библиотеки, наплевавшей на ограничение по длине строки — у меня половина экрана «красная». Это огорчает.
3. В третьих и главное: если у вас широкий монитор — это прекрасная возможность разбить его по вертикали и видеть одновременно несколько редактируемых файлов. У меня даже на 14'' ноутбуке Full HD — это значит что при размере шрифта в 13pt у меня помещается два буфера. Коллега на 24'' привык работать в vim с шестью буферами: 3х2. Это очень удобно — гораздо лучше видеть сразу несколько файлов чем один, но с длинными строками.

Что до «невозможности» уместить код в 79 символов — это распространенное заблуждение.
При некотором навыке всё легко получается.

К тому же такой подход провоцирует сохранение промежуточных вычислений в локальные переменные — что хорошо само по себе, так как улучшает читабельность кода (вы же даете переменным не слишком длинные, но «говорящие» имена, верно?)

Коротко говоря, 79 символов заставляют лучше писать код и помогают его читать. Что вам всем и рекомендую.

Автор: Andrew Svetlov

Перегрузка операций

В питоне буквально все используют магические методы. Когда пишем конструктор класса — называем его __init__ и т.д.

Надеюсь, все умеют писать такие вещи, у меня нет желания останавливаться на основах подробней.

Поговорим о правильной перегрузке математических операций. Читать

exrex генератор данных по регулярным выражениям

Всем привет!

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

API крайне простой
count — возвращет количество возможных вариаций
parse — парсер регулярных выражений
getone — возвращает псевдо-рандомное значение
generate — возвражает генератор со всеми вариантами

Примеры использования

На всякий замечу, что у вас по некоторым примером вывод может быть другим

>>> print exrex.getone('[A-Z][a-z]{1,10} [A-Z][a-z]{1,10}')
Boris Yeltsin

>>> print exrex.getone('+[0-9]([0-9]{3}) [0-9]{3}-[0-9]{2}-[0-9]{2}')
+5(777) 790-68-69

>>> print [r for r in exrex.generate('|'.join(str(i) for i in range(5)))]
[u'0', u'1', u'2', u'3', u'4']

>>> exrex.count('[0-9]{1}')
10

>>> print exrex.parse('[0-9]{1,100}')
[('max_repeat', (1, 100, [('in', [('range', (48, 57))])]))]

Есть также возможность запуска из консоли

>>> python -m exrex -r [0-9]{2}
31
Возвращает псевдо-рандомное число из 2 цифр

За более подробной информацией в ссылки.


Ссылки

https://github.com/asciimoo/exrex
http://exrex.readthedocs.org/

Автор: Евгений Курочкин