python. декоратор метода класса с параметром объекта.
есть ещё вариант передавать имя мутекса строкой, потом из первого аргумента функции брать self, искать там это имя, но это уже какой-то совсем изврат.У тебя в примере mutex всегда self.mutex, зачем передавать имя, если и так знаешь?
в реальном приложении он не один.
передавать имя мутекса строкой, потом из первого аргумента функции брать self, искать там это имя
— нормальный вариант.
def resultfunc(*args, **kwargs):
lock.acquire
try:
return func(*args, **kwargs)
finally:
lock.release
with lock:
return func(...)
И тогда зачем тебе вообще этот декоратор нужен?
до этого try-finally использовал, но в двух местах (лочим, размлочим) - и когда их 2-3разных мутексов уже сложно читать - поэтому решил найти что-нибудь поудобнее.
всем спасибо!
А вот это симпатично.Блин, прочитай уже наконец доки хоть раз.
Да оно там в самом конце, я не увидел.
это всё жуткий бред (не сочти за грубость )import threading
def mutex_decorator(lock):
def wrapper(func,*args, **kwargs):
def resultfunc(*args, **kwargs):
e = None
lock.acquire
try:
ret = func(*args, **kwargs)
except Exception, ex:
e = ex
lock.release
if e:
raise e
return ret
return resultfunc
return wrapper
class MyClass(object):
def __init__(self):
self.mutex = threading.Lock
@mutex_decorator(self.mutex)
def do_something(self):
pass
def main:
c = MyClass
if __name__ == '__main__':
main
этот код показывает, что ты не понимаешь как создаются классы в питоне и как работают декораторы.
разберись с этим! (если, конечно, тебе нужно писать на питоне)
import threading
def mutex_decorator(lock):
def wrapper(func,*args, **kwargs):
def resultfunc(*args, **kwargs):
e = None
lock.acquire
try:
ret = func(*args, **kwargs)
except Exception, ex:
e = ex
lock.release
if e:
raise e
return ret
return resultfunc
return wrapper
class MyClass(object):
mutex = threading.Lock
def __init__(self):
@mutex_decorator(mutex)
def do_something(self):
pass
def main:
c = MyClass
if __name__ == '__main__':
main
Вот так, если без ошибки - что тут не нравится? Ошибка там специально сделана, чтобы показать, что я хочу.
если специально, то беру свои слова назад
Почему так происходит - я понимаю.уверен?
декоратор это не более чем функция которая принимаем функцию на вход и возвращает функцию на выход, никакой магии. тебе её нужно параметризовать не полем self-а, а тем что в С++ называется member-pointer, то есть штучкой, которая задает отображение объектов в какое-то их поле. если у вас в питоне в качестве member-pointer-а нет ничего лучшего чем просто строка-имя-поля, ну значит да, придется через строку, что такого.
и меня уже ткнули в моё незнание stdlib и более красивое использование Lock без декоратора конструкцией в одну строку
Ведь проблема ставилась чуть шире.
Когда много мутексов, можно случайно какой-нибудь не разлочить и если это какая-нибудь редкая ветвь - получить когда-нибудь в будущем дедлок или геморой с поиском на этапе отладки
я питон совсем чуть чуть знаю, но наверняка там можно написать функцию lock(mutext) которая бы возвращала объект, который в деструкторе бы разлочивал этот мутекс. тогда забыть разлочить было бы невозможно. или в питоне трудно контролировать момент деструктора как в яве? в с++ и в перле с этим всё просто, вышла переменная из скопа - вызывается деструктор.
Оставить комментарий
Phoenix
пишет
Почему так происходит - я понимаю.
Как поправить? сейчас вынес мутекс на уровень класса и в декоратор передаю без self, но тогда все экземпляры будут использовать один мутекс, что равносильно просто глобальному мутексу.
есть ещё вариант передавать имя мутекса строкой, потом из первого аргумента функции брать self, искать там это имя, но это уже какой-то совсем изврат.