Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I perform imports in a python module without polluting its namespace?

I am developing a Python package for dealing with some scientific data. There are multiple frequently-used classes and functions from other modules and packages, including numpy, that I need in virtually every function defined in any module of the package.

What would be the Pythonic way to deal with them? I have considered multiple variants, but every has its own drawbacks.

  • Import the classes at module-level with from foreignmodule import Class1, Class2, function1, function2
    Then the imported functions and classes are easily accessible from every function. On the other hand, they pollute the module namespace making dir(package.module) and help(package.module) cluttered with imported functions

  • Import the classes at function-level with from foreignmodule import Class1, Class2, function1, function2
    The functions and classes are easily accessible and do not pollute the module, but imports from up to a dozen modules in every function look as a lot of duplicate code.

  • Import the modules at module-level with import foreignmodule
    Not too much pollution is compensated by the need to prepend the module name to every function or class call.

  • Use some artificial workaround like using a function body for all these manipulations and returning only the objects to be exported... like this

    def _export():     from foreignmodule import Class1, Class2, function1, function2     def myfunc(x):         return function1(x, function2(x))     return myfunc myfunc = _export() del _export 

    This manages to solve both problems, module namespace pollution and ease of use for functions... but it seems to be not Pythonic at all.

So what solution is the most Pythonic? Is there another good solution I overlooked?

like image 950
Tanriol Avatar asked Sep 14 '11 22:09

Tanriol


1 Answers

Go ahead and do your usual from W import X, Y, Z and then use the __all__ special symbol to define what actual symbols you intend people to import from your module:

__all__ = ('MyClass1', 'MyClass2', 'myvar1', …) 

This defines the symbols that will be imported into a user's module if they import * from your module.

In general, Python programmers should not be using dir() to figure out how to use your module, and if they are doing so it might indicate a problem somewhere else. They should be reading your documentation or typing help(yourmodule) to figure out how to use your library. Or they could browse the source code yourself, in which case (a) the difference between things you import and things you define is quite clear, and (b) they will see the __all__ declaration and know which toys they should be playing with.

If you try to support dir() in a situation like this for a task for which it was not designed, you will have to place annoying limitations on your own code, as I hope is clear from the other answers here. My advice: don't do it! Take a look at the Standard Library for guidance: it does from … import … whenever code clarity and conciseness require it, and provides (1) informative docstrings, (2) full documentation, and (3) readable code, so that no one ever has to run dir() on a module and try to tell the imports apart from the stuff actually defined in the module.

like image 168
Brandon Rhodes Avatar answered Sep 21 '22 03:09

Brandon Rhodes