Python function to return listed imports gives empty result, but works line by line
Question: Adapting code from

[How to list imported
modules?](http://stackoverflow.com/questions/4858100/how-to-list-imported-
modules)

to look like

    
    
    def imports():
        import types
    
        Module = None
        Modules = list()
    
        for name, val in globals().items():
            if isinstance(val, types.ModuleType):
                Module = val.__name__
                Modules.append(Module)
    
        return Modules
    

and saved as imports.py. Intended to be activated in the form

    
    
    Modules = imports.imports()
    

Instead, returns an empty list `Modules`.

Have looked here

[Python.org classes +
generators](https://docs.python.org/3.4/tutorial/classes.html#generators)

here

[Python.org Data structures: list
comprehensions](https://docs.python.org/3.4/tutorial/datastructures.html#list-
comprehensions)

and here

[Python return list from
function](http://stackoverflow.com/questions/9317025/python-return-list-from-
function)

and not getting it.

When I run the function body line by line I get the desired result (a list of
the imported modules stored in `Modules`). When it's run as a defined function
it gives an empty list. Why is my returned list variable empty? I've also
tried `yield` with the same result.


Answer: The [`globals()`
function](https://docs.python.org/3/library/functions.html#globals) returns
the global namespace for the _module it is used in_. You are seeing the
modules that are imported in your `imports` module, and there are 0 such
imports. You can't use this function if you wanted to access the globals of
the code that called your function.

You'd have to use the globals of the _calling frame_ instead; in CPython you
can do this with the [`sys._getframe()`
function](https://docs.python.org/3/library/sys.html#sys._getframe), which
returns a frame object; the `f_globals` attribute on that frame is the global
namespace of the caller of your function:

    
    
    caller_frame = sys._getframe(1)
    for name, val in caller_frame.f_globals.items():
    

Alternatively, have the caller pass in a namespace; that way you can list the
modules used in _any_ module:

    
    
    def imports(namespace=None):
        import types, sys
    
        if namespace is None:
            # default: caller globals
            namespace = sys._getframe(1).f_globals
    
        modules = []
    
        for name, val in namespace.items():
            if isinstance(val, types.ModuleType):
                module_name = val.__name__
                modules.append(module_name)
    
        return modules
    

The above version still uses `sys._getframe(1)` if you call the function
without arguments. But you could use it on any dictionary now:

    
    
    import string
    print(imports(vars(string)))
    

This uses the [`vars()`
function](https://docs.python.org/3/library/functions.html#vars) to grab the
namespace dictionary of the `string` module, for example. This produces:

    
    
    >>> import string
    >>> imports(vars(string))
    ['re', '_string']
    

