13

We have all been told using from module import * is a bad idea. However, is there a way to import a subset of the contents of module using a wildcard?

For example:

module.py:

MODULE_VAR1 = "hello"
MODULE_VAR2 = "world"
MODULE_VAR3 = "The"
MODULE_VAR4 = "quick"
MODULE_VAR5 = "brown"
...
MODULE_VAR10 = "lazy"
MODULE_VAR11 = "dog!"
MODULE_VAR12 = "Now"
MODULE_VAR13 = "is"
...
MODULE_VAR98 = "Thats"
MODULE_VAR99 = "all"
MODULE_VAR100 = "folks!"

def abs():
    print "Absolutely useful function: %s" % MODULE_VAR1

Obviously we don't want to use from module import * because we'd be overriding the abs function. But suppose we DID want all of the MODULE_VAR* variables to be accessible locally.

Simply putting from module import MODULE_VAR* doesn't work. Is there a way to accomplish this?

I used 100 variables as an illustration, because doing from module import MODULE_VAR1, MODULE_VAR2, MODULE_VAR3, ..., MODULE_VAR100 would obviously be incredibly unwieldy and wouldn't work if more variables (e.g. MODULE_VAR101) were added.

fdmillion
  • 4,823
  • 7
  • 45
  • 82

2 Answers2

8

You can have a helper function for that - and it can be done without magic:

import re

def matching_import(pattern, module, globals):
    for key, value in module.__dict__.items():
        if re.findall(pattern, key):
            globals[key] = value

Now, you can do for example:

from utils import matching_import
import constants

matching_import("MODULE_VAR.*", constants, globals())

Using globals() explicitly in this way avoids frame introspection magic, which is usually considered harmful.

kuujo
  • 7,785
  • 1
  • 26
  • 21
jsbueno
  • 99,910
  • 10
  • 151
  • 209
6

You can use the __all__ variable to import specific variables when using the import * syntax.

mymodule.py

__all__ = [
  'MODULE_VAR1',
  'MODULE_VAR2',
  'MODULE_VAR3',
  'MODULE_VAR4',
  'MODULE_VAR5',
]

MODULE_VAR1 = "hello"
MODULE_VAR2 = "world"
MODULE_VAR3 = "The"
MODULE_VAR4 = "quick"
MODULE_VAR5 = "brown"

def abs():
  print "Absolutely useful function: %s" % MODULE_VAR1

Then we can use it thusly:

from mymodule import *
print MODULE_VAR1 # hello
print abs # <built-in function abs>

When a module is imported using *, Python checks the module for an __all__ variable which can override what would otherwise be considered the normal "public" variables in the module (which would be variables that don't start with underscores) and allows you to explicitly define which variables are "public". Check out this question

Community
  • 1
  • 1
kuujo
  • 7,785
  • 1
  • 26
  • 21
  • This is great! But is there any way to achieve the same effect if you don't have control over the source code of the module? – seaotternerd Jun 21 '13 at 02:25
  • 1
    Sorry I misunderstood. I don't know of any way to natively import specific variables from another module. But as a very simple solution, you could create a helper that imports the module and iterates over the module's attributes to extract the variables that you want. In your example, this would prevent the `abs` variable from being overridden you're not importing the module variables but the module itself. Alternatively, you *could* import the module variables within the scope of a function, preventing the built-in `abs` function from being overridden. I think @jsbueno has a perfect example. – kuujo Jun 21 '13 at 02:55
  • I don't know if you misunderstood - I wasn't the person who asked the question, I was just curious. Thanks! – seaotternerd Jun 21 '13 at 03:05
  • Oh, good point. I missed that! Haha. But it did still look like I may have misunderstood and the OP was looking more for @jsbueno's answer. – kuujo Jun 22 '13 at 06:42