У меня есть код в декораторе, который я хочу запустить только один раз. Многие другие функции (утилита и прочее) будут вызваны позже по строке, и я хочу, чтобы другие функции, которые могут иметь этот декоратор, случайно не используются в гнезде вызовов функций.Предотвращение вставки функции (или декоратора)
Я также хочу проверить, в любой момент, был ли текущий код завернут в декоратор или нет.
Я написал это, но я просто хотел узнать, может ли кто-нибудь еще подумать о лучшем/более элегантном решении, чем проверять уникальное имя функции (надеюсь,!) В стеке.
import inspect
def my_special_wrapper(fn):
def my_special_wrapper(*args, **kwargs):
""" Do some magic, only once! """
# Check we've not done this before
for frame in inspect.stack()[1:]: # get stack, ignoring current!
if frame[3] == 'my_special_wrapper':
raise StandardError('Special wrapper cannot be nested')
# Do magic then call fn
# ...
fn(*args, **kwargs)
return my_special_wrapper
def within_special_wrapper():
""" Helper to check that the function has been specially wrapped """
for frame in inspect.stack():
if frame[3] == 'my_special_wrapper':
return True
return False
@my_special_wrapper
def foo():
print within_special_wrapper()
bar()
print 'Success!'
@my_special_wrapper
def bar():
pass
foo()
Я думаю, это звучит как случай, когда ваш дизайн нуждается в переосмыслении.Исправьте это на дизайне, а не на техническом уровне. Тип хакера, который вы здесь делаете, - это хрупкое и невероятно необычное поведение, которое, вероятно, путает читателей кода. –
Я не думаю, что это должно быть. Обертка добавляет логику транзакции базы данных, обрабатывает запуск/фиксацию и повторные попытки блокировки и т. Д. Использование этого в качестве декоратора идеально. Транзакции не могут быть вложенными, поэтому мне нужно выбросить ошибку, если это произойдет. –
Достаточно справедливо, это звучит достаточно обоснованно. –