Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 9, 2011 00:56:58

ctocopok
От:
Зарегистрирован: 2011-04-09
Сообщения: 21
Репутация: +  0  -
Профиль   Отправить e-mail  

События, цепочка обработчиков, как проверить наличие обработчика?

Есть проект, в котором реализована работа с events. Типов событий довольно много, и каждое событие может иметь цепочку обработчиков.
Благодаря переопределению __iadd__ , обработчики добавляются очень просто: Event += newhandler

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

В том месте кода, где я имею возможность править исходник, я написал:

def myHandler():
print "now i got a machine gun!"

targetEvent += myHandler
дело сделано, myHandler вызывается при каждом срабатывании targetEvent, но… так как редактируемый мною обработчик в котором я добавляю свой хэндлер, вызывается несколько раз, получается, что у targetEvent вырастает список обработчиков, делающих одно и то же.
targetEvent.__repr__ дает такую картину:
set([
<function myHandler at 0x0FE3F230>,
<function myHandler at 0x12122DF0>,
<function myHandler at 0x0FE3FEB0>,
<function myHandler at 0x0FE3FEF0>,
...еще много раз ...
<function myHandler at 0x0FE12370>])
пробовал конструкцию
if myHandler in targetEvent._eventHandlers_:
pass
else:
targetEvent += myHandler
где targetEvent._eventHandlers_ это набор обработчиков, но меня это не выручило, очевидно, потому что myHandler к моменту этой проверки уже определен по другому адресу.
Можно, конечно, сделать проверку через поиск подстроки с именем функции в str(targetEvent._eventHandlers_), благо myHandler - это мною управляемое имя, и я могу его сделать уникальным, но, наверное, есть способ проще и изящнее?

Простите, если сумбурно.



Advertising the only makes people buy things they don't need.

Офлайн

#2 Ноя. 9, 2011 03:21:45

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

События, цепочка обработчиков, как проверить наличие обработчика?

> так как редактируемый мною обработчик в котором я добавляю свой хэндлер, вызывается несколько раз,
> получается, что у targetEvent вырастает список обработчиков

Как так получается я не понял. Зачем переопределять одну и ту же функцию, делающую одно и то же и подписывать на одно и тоже событие? Это, кстати, ещё и умудриться надо:

for i in range(5):
def handler():
print 'я дурак'
myevent += handler
> +=
Дурной знак. Придумай и используй свои методы с читаемыми именами, например subscribeHandler или registerHandler.

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

..bw



Отредактировано (Ноя. 9, 2011 03:38:02)

Офлайн

#3 Ноя. 9, 2011 09:29:58

ctocopok
От:
Зарегистрирован: 2011-04-09
Сообщения: 21
Репутация: +  0  -
Профиль   Отправить e-mail  

События, цепочка обработчиков, как проверить наличие обработчика?

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



Advertising the only makes people buy things they don't need.

Офлайн

#4 Ноя. 9, 2011 14:09:54

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

События, цепочка обработчиков, как проверить наличие обработчика?

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

А по сути:
>> так как редактируемый мною обработчик в котором я добавляю свой хэндлер, вызывается несколько раз,
>> получается, что у targetEvent вырастает список обработчиков
> Как так получается я не понял. Зачем переопределять одну и ту же функцию, делающую одно и то же и
> подписывать на одно и тоже событие?
> Вообще, если есть вероятность многократной подписки на одно и тоже событие обработчика, который
> должен быть подписан только раз, то что то в коде не так, и желаемая проверка это плохой способ справить
> с проблемой.
Никаких объяснений и возражений не последовало, так что я вряд ли в силе помочь, не мой, похоже, уровень.

..bw



Офлайн

#5 Ноя. 9, 2011 15:55:30

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

События, цепочка обработчиков, как проверить наличие обработчика?

Тут трудно что-либо сказать не зная как реализован __iadd__ у targetEvent. Можете показать код или хотя бы рассказать как это сделано? По сути нужно либо сделать так, чтобы сам __iadd__ не добавлял, либо не добавлять, поняв, что targetEvent уже содержит наш обработчик. В обоих случаях нужны хоть какие-то сведения о targetEvent. Пока вы их не дадите вам никто не поможет.



Офлайн

#6 Ноя. 10, 2011 12:08:22

ctocopok
От:
Зарегистрирован: 2011-04-09
Сообщения: 21
Репутация: +  0  -
Профиль   Отправить e-mail  

События, цепочка обработчиков, как проверить наличие обработчика?

вот реализация event-ов.

class Event(object):
def __init__(self, manager=None):
self._Event__delegates = set()
if manager is not None:
manager.register(self)
return None

def __call__(self, *args):
except:
LOG_CURRENT_EXCEPTION()
continue
for delegate in set(self._Event__delegates):
delegate(*args)
continue

def __iadd__(self, delegate):
self._Event__delegates.add(delegate)
return self

def __isub__(self, delegate):
self._Event__delegates.discard(delegate)
return self

def clear(self):
self._Event__delegates.clear()
т.е. ничего необычного.

в проекте сотни модулей, причем, несколько из них реализованы в .exe-файле, куда также встроен интерпретатор python (то есть, даже не отдельной dll, как иногда бывает), и к этим модулям тоже есть отсылки. Из-за этого, запустить модули отдельно, без .exe, не представляется возможным. Можно только в некоторые события “влезть”.

Пока что, на стадии установки своего “хука” я делаю так:
if str(repr(targetEvent._Event__delegates)).find('myHandler')>-1:
#хук уже есть
pass
else:
targetEvent += myHandler
возможно, определение myHandler тоже надо поместить в ветку “else”, дабы не плодить функции, которые даже не будут использоваться.



Advertising the only makes people buy things they don't need.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version