Thread-safe way to prevent decorator from being nested

Michael mw at d3i.com
Thu Jun 6 12:48:18 EDT 2013


I'm writing a decorator that I never want to be nested. Following from the answer on my StackOverflow question (http://stackoverflow.com/a/16905779/106244), I've adapted it to the following.

Can anyone spot any issues with this? It'll be run in a multi-threaded environment serving Django requests and also be a part of Celery tasks.


    import threading
    from contextlib import contextmanager
    from functools import wraps

    thread_safe_globals = threading.local()

    @contextmanager
    def flag():
        thread_safe_globals._within_special_context = True
        try:
            yield
        finally:
            thread_safe_globals._within_special_context = False

    def within_special_wrapper():
        try:
            return thread_safe_globals._within_special_context
        except AttributeError:
            return False

    def my_special_wrapper(f):
        @wraps(f)
        def internal(*args, **kwargs):
            if not within_special_wrapper():
                with flag():
                    f(*args, **kwargs)
            else:
                raise Exception("No nested calls!")
        return internal

    @my_special_wrapper
    def foo():
        print(within_special_wrapper())
        bar()
        print('Success!')

    @my_special_wrapper
    def bar():
        pass

    foo()



More information about the Python-list mailing list