6

with __init__.py in the directory, I was able to import it by

from subdirectory.file import *

But I wish to import every file in that subdirectory; so I tried

from subdirectory.* import *

which did not work. Any suggestions?

MoneyBall
  • 2,343
  • 5
  • 26
  • 59
  • Maybe I was a bit quick with my answer, is it the case that _for each_ module in `subdirectory` you want to perform `from module import *` (for a variable number of modules)? Although I wouldn't recommend this because it really clutters your namespace. It's better to leave things scoped. – a_guest Jun 29 '17 at 13:12
  • In my subdirectory, I have files which contain only one function. I would be adding more files later on and I would like my code to automatically import everything. Plus I have 2 directories like that. I think your answer should solve my problem except I would have to import them manually and add import everytime I add a file to the subdirectory. – MoneyBall Jun 29 '17 at 13:23

3 Answers3

9

Found this method after trying some different solutions (if you have a folder named 'folder' in adjacent dir):

for entry in os.scandir('folder'):
    if entry.is_file():
        string = f'from folder import {entry.name}'[:-3]
        exec (string)
ninapberry
  • 111
  • 1
  • 3
  • 1
    I like this one because I could easily filter with adding this into loop: `if entry.name[0] != '_':` – J_Scholz Apr 27 '20 at 13:55
7

If you have the following structure:

$ tree subdirectory/
subdirectory/
├── file1.py
├── file2.py
└── file3.py

and you want a program to automatically pick up every module which is located in this subdirectory and process it in a certain way you could achieve it as follows:

import glob

# Get file paths of all modules.
modules = glob.glob('subdirectory/*.py')

# Dynamically load those modules here.

For how to dynamically load a module see this question.


In your subdirectory/__init__.py you can import all local modules via:

from . import file1
from . import file2
# And so on.

You can import the content of local modules via

from .file1 import *
# And so on.

Then you can import those modules (or the contents) via

from subdirectory import *

With the attribute __all__ in __init__.py you can control what exactly will be imported during a from ... import * statement. So if you don't want file2.py to be imported for example you could do:

__all__ = ['file1', 'file3', ...]

You can access those modules via

import subdirectory
from subdirectory import *

for name in subdirectory.__all__:
    module = locals()[name]
a_guest
  • 34,165
  • 12
  • 64
  • 118
  • How do I use `__all__` exactly? `__all__` seems like a list of strings of file names. Do iterate `__all__` in a for loop and do import? – MoneyBall Jun 29 '17 at 13:24
  • @MoneyBall I edited my answer. You can use `from .file import *` in `__init__.py` if you really want to import all the content. Note that if the different modules have attributes with the same name they will shadow each other. You might also want to take a look at [this answer](https://stackoverflow.com/a/21221452/3767239). – a_guest Jun 29 '17 at 13:30
  • There won't be any overlaps since every function is same as its file name. sorry but i'm still confused. You have `module = locals()[name]`. What exactly is this line doing? – MoneyBall Jun 29 '17 at 13:34
  • Also is there an easier way to import everything in `__init__.py`? Like `from * import *`? – MoneyBall Jun 29 '17 at 13:35
  • @MoneyBall `from subdirectory import *` brings the different modules in the local namespace (`locals()`). `module = locals()[name]` gives you the module of the specific `name`. You can then access its attributes via `getattr(module, name)` (if the function has the same name as the module). If you want your program to automatically realize new modules then you could parse the directory via `glob.glob('subdirectory/*.py')` and [dynamically load](https://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path) those modules. – a_guest Jun 29 '17 at 13:37
3

Your __init__.py file should look like this:

from file1 import *
from file2 import *

And then you can do:

from subdirectory import *
Ofer Sadan
  • 11,391
  • 5
  • 38
  • 62