0

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?

Community
  • 1
  • 1
duckworthd
  • 14,679
  • 16
  • 53
  • 68

3 Answers3

1

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.

duckworthd
  • 14,679
  • 16
  • 53
  • 68
1

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

Community
  • 1
  • 1
Prahalad Deshpande
  • 4,709
  • 1
  • 20
  • 22
0

You could always pass your callers globals dictionary in to the function and then add to it.

Steve Barnes
  • 27,618
  • 6
  • 63
  • 73