0

I am defining several functions in a python package composed of several modules that represent separate components of a simulation model.

To execute the simulation model, the package is imported and the functions along with their __name__ are extracted by iterating through the modules' __dict__ like this:

import model # The package containing python modules

import inspect
import types

# Get the modules defined in the package
modules = [v for v in vars(model).values() if isinstance(v, types.ModuleType)]

funcs = {}

# Iterate through modules in python package
for module in modules:
    # Go through objects in module `__dict__`
    for name, obj in vars(module).items():  # decorated functions no longer appear here
        # Check for functions
        if isinstance(obj, types.FunctionType):
            # Make sure that the function is defined within the model package
            mod, *sub_mod = inspect.getmodule(obj).__name__.split('.')
            if mod == model.__name__:
                # Store the function along with its name
                funcs[name] = obj

However, when I am debugging this code I'm noticing that some functions that should be in vars(module).items() are not. This happened after applying an lru_cache decorator to some of the functions, which are precisely the ones not showing up.

Why after applying a decorator to some of the functions in the python package do they not show up in the module's __dict__ for which they are defined?

Is there a way to still be able to apply the decorator and have the functions show up in vars(module).items()?

pbreach
  • 16,049
  • 27
  • 82
  • 120
  • 2
    Well, they're not showing up because lru_cache is a factory for "_lru_cache_wrapper" instances, which are just callable objects. So, you're filtering them out with the FunctionType check. – mwchase Jan 04 '17 at 20:07
  • Ah, okay. For some reason I though they would show up as functions. I can't go with callables so I ended up just doing this check instead, `if isinstance(obj, (types.FunctionType, functools._lru_cache_wrapper)`. Everything else works great! Feel free to post an answer. – pbreach Jan 04 '17 at 20:20

1 Answers1

2

The problem is that when you wrap a function with lru_cache, the result is only a callable object, and not a function. The precise type is functools._lru_cache_wrapper.

I originally posted this as a comment. pbreach's solution was to replace types.FunctionType with (types.FunctionType, functools._lru_cache_wrapper), because callable() was too broad a net.

mwchase
  • 811
  • 5
  • 13