I would like to construct a function that emulates from package_name import *. While this question answers how one might do so by modifying globals(). globals(), however, is local to the module the function is defined in.
For example, suppose I define the following function in first_package.py,
import imp
def load_contents(path):
"""Load everything from another package"""
module = imp.load_source('', path)
for k in dir(module):
if not '__' in k: # ignore __xxx__ private variables
globals()[k] = getattr(module, k)
Then run the following code in second_package.py
import first_package
first_package.load_contents('third_package.py')
Nothing will happen. How can I fix this?
3 Answers 3
The trick is to use sys._getframe to go up the call stack 1 step, then retrieve the globals of the caller. The precise code is,
def load_contents(path):
"""Load contents of another configuration file"""
module = imp.load_source('', path)
glob = sys._getframe(1).f_globals # globals of calling module
for k in dir(module):
if not '__' in k: # ignore __xxx__ private variables
glob[k] = getattr(module, k)
Note that this code will only work with CPython, as sys._getframe is an implementation-specific function.
Comments
You can create a dictionary variable within first_package.py that is a cross module variables. Please refer to the link here on how to go about defining a cross module variable. Refer to the response provided by J.F.Sebastian
It is always good to adopt a simple approach that does not play around with python internal mechanisms - since there may be side-effects of such activities in a complex application
Comments
You could always pass your callers globals dictionary in to the function and then add to it.