3

I am looking to import a set of modules from a subdirectory into a single main module in the parent directory:

Project/

main.py
subdirectory/
    __init__.py
    timer.py
    example.py

I can ask for any of the individual .py files like so:

from subdirectory import timer.py

But, if I run the following command,

from subdirectory import *

and I try to use a module within that subdirectory, I get the following error:

File "My:\Path\Here\...", line 33, in main
t = timer.timer()
NameError: name 'timer' is not defined

I want to be able to import all of the files in one batch, as I am importing a couple of modules. I already added a blank init.py file to the subdirectory. Is there anything that I am missing?

Selcuk
  • 57,004
  • 12
  • 102
  • 110
Lee
  • 67
  • 5

3 Answers3

3

You must declare your module names using __all__ in your __init__.py:

__init__.py:

__all__ = ["timer", "example"]

This behaviour is documented:

The only solution is for the package author to provide an explicit index of the package. The import statement uses the following convention: if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered.

Selcuk
  • 57,004
  • 12
  • 102
  • 110
  • Thank you so much! The import * statement works properly now, and I can use the modules that I imported. – Lee Oct 25 '20 at 23:48
2

If you want to just make the imports work, then add subdirectory/__init__.py with the following content:

from * import example
from * import timer

However, if you want to do this to an arbitrary number of (old and new) modules, I think this answer might be what you are looking for:

You start with the following structure:

main.py
subdirectory/
subdirectory/__init__.py
subdirectory/example.py
subdirectory/timer.py

Then import everything in subdirectory from main.py:

from subdirectory import *
t = timer.timer()

Then add the following to the subdirectory/__init__.py module:

from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not 
f.endswith('__init__.py')]

And for completeness sake the subdirectory/timer.py module:

def timer():
    return 42
André C. Andersen
  • 8,955
  • 3
  • 53
  • 79
0

Imports go like this.

# if you have timer.py, import it as 
import timer

Try adding __init__.py to the subdirectory. It will now look like:

Project/


    main.py
    subdirectory/
                 __init__.py
                 timer.py
                 example.py

If that does not work: in main.py add

import sys
sys.path.append("path/to/subdirectory") # replace with the path
import timer
tominekan
  • 303
  • 2
  • 10