MySQLdb.escape — сломали и не сказали Среда, Окт 31 2007 

Политику прочь! Поговорим немножко о питоне.

У соединений MySQLdb всегда был такой метод — escape(), который принимал строку, кавычил её и экранировал опасные символы. Необязательно строку, на самом деле, что угодно. Так или иначе, вот он был, был, и прекрасно работал. Обычно он никому не нужен, потому что параметры запроса эскейпятся автоматически, если передавать их в запрос именно как параметры cursor.execute(query, params), а не вставлять тупо в строку. Но когда собираешь длинный запрос вручную, бывает проще использовать escape().

И вот я пишу что-то такое:

Python 2.4.1 (#2, May  5 2005, 11:32:06) 
>>> import MySQLdb as m
>>> c = m.connect(host='mysql.example.com', user='user', passwd='pass')
>>> print c.escape('123')
Traceback (most recent call last):
  File "", line 1, in ?
TypeError: no default type converter defined

(далее…)

R/W Lock in Python Четверг, Окт 4 2007 

Кто-то в комментах намекал, чтоб я написал что-нибудь о Питоне. Ну вот, дождались.

Понадобился мне read-write lock. Что это такое? Расскажу. Поскольку не все тут программисты, начну от печки.

Программы бывают многопоточные (multi-threaded), то есть несколько действий могут выполняться как-бы-одновременно. Данные программы доступны из всех потоков; при этом программист, вообще говоря, не знает, когда происходит переключение между выполняемыми действиями. Представьте, например, такую функцию:

def increase():
    global x
    y = x
    ... # сделать много чего
    x = y + 1

Эта функция берёт глобальную переменную х, запоминает её значение, долго что-то делает, потом записывает в х значение, на единицу большее. Представьте, что в двух потоках стартует эта функция, назовём их копия1 и копия2.

  1. копия1 стартует и читает значение х — допустим, оно равно 5. Начинает делать много чего
  2. переключение потока
  3. копия2 стартует и читает значение х = 5. Начинает делать много чего
  4. переключение потока
  5. копия1 доделывает много чего, записывает в х значение 6
  6. переключение потока
  7. копия2 доделывает много чего, записывает в х значение 6

В результате после двух вызовов increase() значение х увеличилось только на единицу. Вряд ли программист будет доволен.

Это и есть Великая Проблема Многопоточного Программирования.

Есть такие сущности, которые позволяют решать эту проблему. Простейшая штука — mutex, он же lock (эй, спецы, есть какая-то тонкая семантическая разница?..). Lock можно взять (acquire) и отпустить (release). Если в одном потоке я его захватил, то другой поток не сможет его взять, пока я не отпущу его в первом, и будет вынужден ждать. Так что если создать какой-то lock и в начале нашей функции increase() его захватывать, а в конце отпускать, то переменная х будет увеличиваться, как надо. (Фактически, два экземпляра increase() не будут выполняться параллельно.)

Да, а read-write lock — это такой lock, который позволяет большому (неограниченному) количеству потоков захватывать себя «на чтение» (реальный смысл зависит от программиста),и только одному — «на запись» (разумеется, нельзя начинать писать, пока кто-то читает, и нельзя читать, пока кто-то пишет). Проблема в том, что простой lock, так же как семафор и кое-что ещё, входит в стандартную библиотеку Питона, а вот R/W Lock, к сожалению, нет.

Ваня поделился со мной одной из реализаций, которая используется в Django, и она уже довольно сильно взорвала мой мозг (чего стоит одна идея инициализировать семафор залоченным состоянием!), но когда мне показалось, что я начинаю понимать, как она работает, чёрт дёрнул меня поискать её в Сети (Ваня прислал мне её файлом). Выяснилось, что RWLock не писал только ленивый, и каждый следующий вариант страшнее предыдущего.

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

Ещё говорят, не сломалось — не чини. Поэтому я пока обойдусь первым вариантом, джанговским. Было бы любопытно сравнить различные варианты, но это может полдня занять, увы. А он уже кончился.

Неприятно, что при постулируемом «batteries included» такой востребованной штуки нет в стандартной библиотеке. Может, добавят?

Хорошо, когда есть, к кому пойти за советом. Знания передаются из рук в руки.

Многопоточное программирование требует аккуратности.

Вот и всё, что я могу сказать о программировании на сегодня. Рассуждать о судьбах блогосферы как-то проще.