2009-12-17 2 views
21

Все в мире Django, кажется, ненавидят threadlocals (http://code.djangoproject.com/ticket/4280, http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser). Я прочитал эссе Армина об этом (http://lucumr.pocoo.org/2006/7/10/why-i-cant-stand-threadlocal-and-others), но большая часть его зависит от threadlocals, потому что он неэлегантен.Что так плохо с threadlocals

У меня есть сценарий, где theadlocals значительно упростит ситуацию. (У меня есть приложение, в котором у людей будут поддомены, поэтому все модели должны иметь доступ к текущему субдомену, а их передача из запросов не стоит того, если единственная проблема с threadlocals заключается в том, что они неэлегантные или делают для хрупких код.)

Также много фреймворков Java, похоже, многократно использует threadlocals, так как их случай отличается от Python/Django?

+0

Попробовав реализовать поддомен мульти-аренду квартиры без threadlocals, я могу полностью сочувствовать , После некоторых серьезных разочарований, threadlocals действительно оказался единственным способом. Я читал аргументы против них, и они были недостаточно сильными. Я считаю, что отказ от использования threadlocals является одной из основных причин того, что структура сайтов настолько бесполезна для некоторых сценариев. Будет интересно, если они когда-либо выяснят, как законно разрешить https://code.djangoproject.com/ticket/15089 таким образом, который можно адаптировать к типу многопользовательской аренды, которую вы и я используем, без них. –

+0

Ссылка на Django Cookbook не работает. Ссылка на эссе также сломана ([возможная замена] (http://www.memonic.com/user/pneff/folder/python/id/1Wg)). –

ответ

18

Я не думаю, что с threadlocals что-то не так - да, это глобальная переменная, но, кроме того, это обычный инструмент. Мы используем его только для этой цели (сохраняя модель поддомена в контексте глобального для текущего запроса от промежуточного программного обеспечения), и он отлично работает.

Итак, я использую правильный инструмент для работы, в этом случае threadlocals делают ваше приложение более элегантным, чем прохождение модели поддомена во всех методах модели (не говоря уже о том, что это даже не всегда возможно - когда вы переопределяете методы диспетчера django для ограничения запросов по субдомену, у вас нет способа передать что-либо лишнее в get_query_set, например, так что threadlocals - это естественный и единственный ответ).

+0

От кого-то, кто реализовал то же самое (мы сохраняем запрос, а не модель, но к тому же концу). Я полностью согласен. Люди будут бороться против threadlocals, пока им не понадобится реализовать динамичный многопользовательский договор с django, и в этот момент они поймут, что это определенно одна из тех «практичности, которая превосходит чистоту». –

+1

делает приложение более элегантным, скрывая зависимости? Впервые я это прочитал. В понимании, что django не может позволить вам сделать это каким-либо другим способом. Это вопрос джанго. Но элегантно, давайте соглашаться на это. – graffic

2

Вы хотите использовать threadlocals, когда работаете с несколькими потоками, и хотите локализовать некоторые объекты в определенном потоке, например. с одним подключением к базе данных для каждого потока. В вашем случае вы хотите использовать его скорее как глобальный контекст (если я вас правильно понимаю), что, вероятно, является плохим. Это сделает ваше приложение немного медленнее, более сложным и сложнее тестировать.

Зачем передавать его из запроса не стоит? Почему вы не храните его в сеансе или в профиле пользователя?

Разница с Java заключается в том, что в веб-разработке гораздо больше состояний, чем в Python/PERL/PHP/Ruby, поэтому люди привыкли ко всем типам контекстов и тому подобному. Я не думаю, что это преимущество, но вначале это похоже.

+0

'Почему вы не храните его в сеансе или в профиле пользователя? Потому что мне нужно получить доступ к нему из моделей. – agiliq

+0

'В вашем случае вы хотите использовать его скорее как глобальный контекст. NOt действительно, я хочу установить его в Middleware и использовать его в modles.py без представлений, отправляя его в models.py явным образом каждый раз , – agiliq

3

Также много фреймворков Java, похоже, многократно использует threadlocals, так как их случай отличается от Python/Django?

Интерпретатор CPython имеет глобальную блокировку интерпретатора (GIL), что означает, что интерпретатор может обрабатывать только один поток Python в любой момент времени. Мне не ясно, что для реализации интерпретатора Python обязательно потребуется использовать более одного потока операционной системы, хотя на практике это делает CPython.

Главный механизм блокировки Java - через блокировки объектов. Это децентрализованный подход, который позволяет использовать несколько параллельных потоков на многоядерных и многопроцессорных процессорах, но также создает гораздо более сложные проблемы синхронизации для программиста.

Эти проблемы с синхронизацией возникают только при условии «shared-mutable state». Если состояние не изменено, или, как в случае с ThreadLocal, оно не является общим, то это одна менее сложная проблема для программиста Java.

Программист CPython по-прежнему должен иметь дело с возможностью условий гонки, но некоторые из более эзотерических проблем Java (например, публикации), по-видимому, решаются интерпретатором.

Программист CPython также имеет возможность кодирования критического кода производительности в коде C или C++, вызываемом Python, где ограничение GIL не применяется. Технически Java-программист имеет аналогичный вариант через JNI, но это правильно или неправильно считается менее приемлемым в Java, чем в Python.

22

Я избегаю такого рода использования threadlocals, потому что он вводит неявное нелокальное соединение. Я часто использую модели во всех видах не-HTTP-ориентированных способов (локальные команды управления, импорт/экспорт данных и т. Д.). Если я получаю доступ к некоторым данным threadlocals в models.py, теперь я должен найти способ убедиться, что он всегда заполняется всякий раз, когда я использую свои модели, и это может стать довольно уродливым.

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

Если я абсолютно не мог найти способ хранения данных запроса в threadlocals, я бы, по крайней мере, реализовал методы-оболочки в отдельном модуле, который обращается к threadlocals и вызывает методы модели с необходимыми данными. Таким образом, models.py остается автономным, и модели могут использоваться без муфты threadlocals.

+1

Carl: Я согласен, что это ломает местность, но если мне нужно передать данные «subdoain» во всех 100% моих вызовов '.filter', разве это не ухудшит DRY. Вот почему я считаю, что это приемлемый компромисс в этом случае. – agiliq

+7

Компромисс может быть приемлемым в этом случае; только вы можете сделать этот звонок. Вы спросили: «Что так плохо с threadlocals», поэтому я ответил :-) Я также описал, как я мог бы уменьшить ущерб, если бы чувствовал, что компромисс стоит того. –

+1

Подход в Django должен заключаться в создании промежуточного программного обеспечения запроса, которое связывает локальные данные потока с объектом запроса. Это следует за дизайном Django для структуры сеанса, благодаря которому класс промежуточного программного обеспечения гарантирует наличие достаточного количества данных, которое ваше приложение не взорвет, если вы хотите получить доступ к некоторым данным для каждого запроса. Это также означает, что такая обидчивая связь доступна только через представления, которые я, по-моему, никому не ограничил для разработки своего приложения. –

0

Я нашел использование ThreadLocal - отличный способ реализовать инъекцию зависимостей в среде HTTP-запроса/ответа (т. Е. Любой webapp). Вы просто настроили фильтр сервлета, чтобы «вставить» нужный объект в поток при получении запроса и «uninject» его при возврате ответа.

Это умный человек DI без всякого уродства XML, без MB Spring Jars (не говоря уже о его кривой обучения) и без всякой загадочной повторяющейся номенклатуры @annotation и потому, что он не индивидуально вводит множество экземпляров объектов с помощью зависимости, вероятно, это намного быстрее и использует меньше памяти.

Он работал так хорошо, мы открыли соерсед нашего exPOJO фильтра, который может впрыснуть сеанс Hibernate или JDO PersistenceManager с помощью ThreadLocal:

http://www.expojo.com