LINUX.ORG.RU

[django] Объект, который создан однажды и доступен все время

 


0

0

Есть класс, в котором реализованы некие приблуды (грубо говоря, словарь {sessionid: jabber-соединение, ...}), и мне хотелось бы, чтобы объект этого класса создавался бы однажды и был бы доступен при вызове любого вида (view).

Приведу пример: есть class My(list): pass. В index(request) создается экземпляр x = My и, допустим, выполняется x.append(JabberClient(jid="foo@bar")), пока все нормально. Но index свое отработал - объект удаляется, и при следующем вызове index я получу x == [], вместо желаемого [<JabberClient ...>].

Реализовывать все это через сокеты и делать какой-то свой протокол (если сказал глупость - сильно не пинать, не прошарен в этом деле) меня пугает. Реализация через cPickle + файл/fifo мне кажется невозможной. Нагуглил что-то про PyDispatcher, но ничего внятного не понял.

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

Ответ на: комментарий от teferiincub

facepunch.jpg

Слона то я и не приметил. Спасибо.

Werehuman ★★
() автор топика

> Реализация через cPickle + файл/fifo мне кажется невозможной

Если через сериализацию не получится, то через сессии тем более. Ибо они не более чем сериализованный и записанный в базу данных dict.

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

dccp
()
Ответ на: комментарий от dccp

Таки да, решил перевести все на сессии, а это оказалось невозможным.

"Unhandled Exception

An unhandled exception was thrown by the application."

Можно поподробнее про "соединение при каждой необходимости, либо пул соединений создавать"?

Werehuman ★★
() автор топика

а тебе не синглтон случайно нужен?

как пример вот 
class Singleton(object):
	"""
	In [2]: class Foo(Singleton):
	   ...:     def __init__(self, x):
	   ...:         self.x = x
	   ...:         
	In [3]: a = Foo(10)
	In [4]: b = Foo()
	In [5]: print a.x, b.x
	10 10
	In [6]: print id(a) == id(b)
	True
	In [7]: z = Foo(1)
	AssertionError: Instance, already initialized
	"""
	
	_single = None
	def __new__(classtype, *args, **kwargs):
		if classtype._single is None:
			classtype._single = object.__new__(classtype)
			if hasattr(classtype._single, '__init__'):
				classtype._single.__init__(*args, **kwargs)
				try:
					del classtype.__init__
				except AttributeError:
					pass
		else:
			assert not (args or kwargs), 'Instance, already initialized'
		return classtype._single


и вынести его инициализацию в пространство модуля

obj = SingleObj()

def view(request):
    obj.append()

зы ну и в своем коде не забыть про треды )

Minmax
()
Ответ на: комментарий от Minmax

> а тебе не синглтон случайно нужен?

Возможно, оно.

Werehuman ★★
() автор топика
Ответ на: комментарий от z0D5e8n7x_2

> собственно не понял, чего не срослось с сессиями?

При request.session["jabberclient"] = jabberclient вылетает ошибка, написанная выше.

Werehuman ★★
() автор топика
Ответ на: комментарий от Werehuman

А, ну да, я через nginx пускаю - видимо это его ответ.

Werehuman ★★
() автор топика

я бы поднял отдельного демона, который держит соединения и хранит в себе словарь SID=> Connect. Джанга же обращалась бы к этому демону, получала список SID и просила этого демона что-то сделать.

Liosha_Syrnikov
()
Ответ на: комментарий от Sphinx

>Это не ошибка, это 500 пролетела через трусы джанги, поставь DEBUG = True.

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

z0D5e8n7x_2
()
Ответ на: комментарий от z0D5e8n7x_2

> ну и как бы, при разработке наверно лучше пользоваться встроенным сервером...

Очень спорное утверждение. Я, например, встроенный сервер ни разу даже не запускал - благо апач поставить 1 команда.

Расскажите как на однопоточном встроенном сервере разрабатывать многопоточные AJAX-приложения?

А еще потом начнутся косяки из-за того, что на продакшне другая конфигурация.

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

dccp
()
Ответ на: комментарий от dccp

Настолько суровы

Ага, и толкать коммиты прям на продакшен — дисциплинирует,
прекоммит тесты сразу уважать начинаешь :)

Sphinx ★★☆☆
()

(Еще не пробовал) Кстати да, синглтон точно будет везде доступен, если учесть, что джанга форкается при старте несколько раз?

Werehuman ★★
() автор топика
Ответ на: комментарий от Sphinx

> поставь DEBUG = True.

Итак стоит.

Посмотрел через standalone-сервер (кстати, при нем почему-то xmpppy отказалось коннетиться, надо будет всех миниботов на pyxmpp перетащить).

Traceback (most recent call last):

  File "/usr/lib/python2.6/site-packages/django/core/servers/basehttp.py", line 278, in run
    self.result = application(self.environ, self.start_response)

  File "/usr/lib/python2.6/site-packages/django/core/servers/basehttp.py", line 635, in __call__
    return self.application(environ, start_response)

  File "/usr/lib/python2.6/site-packages/django/core/handlers/wsgi.py", line 243, in __call__
    response = middleware_method(request, response)

  File "/usr/lib/python2.6/site-packages/django/contrib/sessions/middleware.py", line 35, in process_response
    request.session.save()

  File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/db.py", line 53, in save
    session_data = self.encode(self._get_session(no_load=must_create)),

  File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/base.py", line 88, in encode
    pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)

UnpickleableError: Cannot pickle <type 'thread.lock'> objects

Это прямо в окне браузера. Собственно, про что говорили выше.

Werehuman ★★
() автор топика

Вообще, в данном случае проще всего написать мидлварь http://docs.djangoproject.com/en/dev/topics/http/middleware/#topics-http-midd...

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

provaton ★★★★★
()
Ответ на: комментарий от Werehuman

Ты что-то не так настроил в сессии, прозреваю я. Случайно лок не пихаешь в нее? Проверь, мидлварь сессий включена? Именно там, где должна быть включена?

Кстати, дарю идею: если тебе нужно, чтобы значение сохранялось один раз для всего времени выполнения проекта, можно сделать синглтон, конечно, но можно хитрее:

def my_view(request, holder=[]):
    holder.append(zzz)

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

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

anonymous4
()
Ответ на: комментарий от anonymous4

Сессии работают нормально, бэкенд - db.

Насчет holder=[] наверное не выйдет - этот объект используется в нескольких видах, а судя по описанию, он будет действовать только в пределах одного вида.

Werehuman ★★
() автор топика
Ответ на: комментарий от Werehuman

>будет действовать только в пределах одного вида

Конечно. В принципе можно написать декоратор для всех видов, которые будут использовать этот синглтон. Главная прелесть такого подхода (если не считать, что он confusing, trouble-asking и bug-magnet), что во-первых не нужно гадить ни в каком глобальном неймспейсе и во-вторых объект создается только тогда когда он на самом деле нужен.

anonymous4
()

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

Werehuman ★★
() автор топика
Ответ на: комментарий от Werehuman

>Придется делать отдельную прогу.

Разумно. Связность системы меньше + юниттестить проще.

anonymous4
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.