简体   繁体   中英

Python, import functions from modules

I have many modules (hundreds). In each module I have at least one function. My question is how can I import all functions from all modules with only one line? Because I do not want to do it like this:

from tests.test_001 import test_001_func
from tests.test_002 import test_002_func
from tests.test_003 import test_003_func
...
from tests.test_999 import test_999_func

test_xxx are modules and these modules contains test_xxx_func function, all modules are in one folder.

I would like use something like this:

from tests import *
test_001.test_001_func()

But this is not working

Create a __init__.py file in the tests directory and in it put:

__all__ = [
    "test_001_func", "test_002_func", # etc
    ]

Then you can either:

import tests

tests.test_001_func()

or

from tests import *  # Not the best way to do things.

NB The reason that the import * is not the prefered solution is that you loose the namespace from the calls so you can a) possibly have collisions with names from other modules and b) your code is less clear.

You need to provide an index of the contents of the tests package by including an __all__ list in the package's __init__.py file.

in your case, the __init__.py file in the tests directory would have something like:

__all__ == ["test_001", "test_002" <<etc...>>]

See the docs on importing * from a package .

Your could automate import using script below.

Assume that folders structure is the next:

run.py
tests
  -> test_001.py
  -> test_002.py

code for tests/__init__.py

import os
import sys

# Append to path "test" folder (also can be any other name)
sys.path.append(os.path.basename(os.path.dirname(__file__)))

__all__ = []
for k in xrange(1, 3):
    name = "test_%03d" % k

    # __import__ can load module by string name
    globals()[name] = __import__(name)

    # set that we export only required names like test_001, test_002
    __all__.append(name)

Code for test_001.py:

def test_001_func():
    print "test1"

Code for test_002.py:

def test_002_func():
    print "test2"

Code for run.py: import tests

print tests.test_001
print tests.test_001.test_001_func

print tests.test_002

The output of the run.py script will be the next:

test@test:~/Desktop/python$ python run.py 
<module 'test_001' from 'tests/test_001.pyc'>
<function test_001_func at 0xb728b09c>
<module 'test_002' from 'tests/test_002.pyc'>

As other answers pointed out, it all boils down to filling __all__ , but I guess you could automate things a bit:

# In your tests/__init__.py do something along the following lines:

import os.path, pkgutil, importlib
__path = os.path.dirname(__file__)
__all__ = [name for _, name, _ in pkgutil.iter_modules([__path])]
for __module in __all__:
    importlib.import_module("." + __module, __name__)

The code is Python 2.7+ due to importlib , but it can be modified for obsolete Python versions by using bare __import__ .

Then use it like this:

import tests
tests.test_002.test_002_func()

Or

from tests import *
test_002.test_002_func()

However , if this is for unit testing, I strongly suggest taking a look at unittest or something like Nose , that will handle test discovery in a more Pythonic way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM