3

I have a question in python, if someone can please help Here is example, I have a contextmanager as below

from contextlib import contextmanager

@contextmanager
def main_func(name):
    print("<%s>" % name)
    yield
    print("</%s>" % name)
    # Retreive the list of function here : tag_func1 and tag_func2 then run the one I need to run

then use it like below

with main_func("h1"):
   def tag_func1():
       print("foo1")

   def tag_func2():
       print("foo2")

I would like to know is possible to retreive the list of function defined in the with statement here tag_func1 and tag_func1 and run them dynamically in the code.

I need to perform those actions into the function main_func implementing the contextmanager

Many thanks for you help,

  • 2
    No, that's not what context managers do. They only define behavior for when you enter and exit the block; they don't have any access to or control over what happens inside the block. See [this question](http://stackoverflow.com/questions/21248103/is-it-possible-to-access-the-context-object-code-block-inside-the-exit-m) and [this one](http://stackoverflow.com/questions/20767038/is-it-possible-to-access-enclosing-context-manager). – BrenBarn Jan 16 '15 at 08:16
  • Context managers don’t even create a separate scope, so whatever you define inside is also locally defined outside of it. – poke Jan 16 '15 at 09:17

1 Answers1

1
class ContextManager():

    def __init__(self):
        self.functions = []

    def func(self, f):
        self.functions.append(f)
        return f

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        for f in self.functions:
            print(f.__name__)


with ContextManager() as cm:

    @cm.func
    def add(x, y):
        return x + y

    def foo():
        return "foo"

    @cm.func
    def subtract(x, y):
        return x - y


# this code prints "add" and "subtract"

This custom context manager has access to all functions defined inside of the with statement that are decorated with func method.

Bartosz Marcinkowski
  • 6,651
  • 4
  • 39
  • 69
  • Great, looks like this solution it's even better than what I wanted to do. I will test that now. Many thanks – – skullomania Jan 16 '15 at 14:15
  • Tested and it works perfectly fine with my Class. Many thanks again. Just a quick one, is there a way by any chance to use another name that cm.func ? cm.go ( example :) ) – skullomania Jan 16 '15 at 14:17
  • Of course there is, just change `def func(self, f)` to `def go(self, f)` in `class ContextManager`. If my answer solved your problem, accept it (click the tick), so that others users with that problem know that my solution works. – Bartosz Marcinkowski Jan 16 '15 at 14:34
  • Note, though, that you can do this without a context manager. Just make a decorator that stores the functions it decorates. Making it a context manager isn't really gaining you anything here. – BrenBarn Jan 16 '15 at 18:21
  • It depends on what @skullomania does in `__enter__` and `__exit__`. – Bartosz Marcinkowski Jan 16 '15 at 19:20