I have a folder with multiple files containing a lot of different classes. These could all be in one big file but for the sake of making it a bit easier to read I've split it up in multiple files depending on what the classes belongs to.
I'd like to import all classes from all files in the folder into the __init__
file so that I can import anything from the folder without knowing in what file it belongs to.
Example:
/kitchen + __init__.py + fridge.py + stove.py + cupboard.py
Now I have to do
from kitchen.fridge import milk
When I'd like to do
from kitchen import milk
The equivalent of this I can get through in __init__.py
do:
from kitchen.fridge import * from kitchen.stove import * from kitchen.cupboard import *
And then I can do
from kitchen import milk
But I'd like it to take all files in the folder without having to specify it explicitly (so that files can be dumped there and then used).
Is there any way of doing this?
__import__() Parameters name - the name of the module you want to import. globals and locals - determines how to interpret name. fromlist - objects or submodules that should be imported by name. level - specifies whether to use absolute or relative imports.
Python __all__ is a list of public objects of that module, as interpreted by import *. The __all__ overrides the default of hiding everything that begins with an underscore.
The __init__.py file makes Python treat directories containing it as modules. Furthermore, this is the first file to be loaded in a module, so you can use it to execute code that you want to run each time a module is loaded, or specify the submodules to be exported.
We can use import * if we want to import everything from a file in our code. We have a file named functions.py that contains two functions square() and cube() . We can write from functions import * to import both functions in our code. We can then use both square() and cube() functions in our code.
import os, sys dir_path = os.path.dirname(os.path.abspath(__file__)) files_in_dir = [f[:-3] for f in os.listdir(dir_path) if f.endswith('.py') and f != '__init__.py'] for f in files_in_dir: mod = __import__('.'.join([__name__, f]), fromlist=[f]) to_import = [getattr(mod, x) for x in dir(mod)] # if isinstance(getattr(mod, x), type)] # if you need classes only for i in to_import: try: setattr(sys.modules[__name__], i.__name__, i) except AttributeError: pass
This is a very bad idea. If you want to add a mechanism for files to be "dumped there and used", you probably want to come up with a plugin scheme, and explicitly search the plugin directory(ies).
The way you normally do this is to iterate one or more plugin directories with os.listdir
or os.walk
, then, for each Python file, use importlib
(or lower-level equivalents from imp
, in Python 2.x) to import it by path.
However, if you really insist on faking things this way inside a package, you can do basically the same tricks within the __init__.py
file, using os.path.dirname(__file__)
as the plugin directory.
And, if you really insist on doing the equivalent of from foo import *
instead of import foo
by path, that's just as easy—or, alternatively, you can use execfile
.
If you don't know how to do these simple things, or how to look them up in the docs… then you definitely shouldn't be attempting this. So, I won't provide sample code in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With