I have a directory structure as follows:
| main.py
| scripts
|--| __init__.py
| script1.py
| script2.py
| script3.py
From main.py
, the module scripts
is imported. I tried using pkgutils.walk_packages
in combination with __all__
, but using that, I can only import all the submodules directly under main
using from scripts import *
. I would like to get them all under scripts
. What would be the cleanest way to import all the submodules of scripts
so that I could access scripts.script1
from main
?
EDIT: I am sorry that I was a bit vague. I would like to import the submodules on run-time without specifying them explicitly in __init__.py
. I can use pkgutils.walk_packages
to get the submodule names (unless someone knows of a better way), but I am not sure of the cleanest way to use these names (or maybe the ImpImporters that walk_packages
returns?) to import them.
I've played around with Joe Kington's Answer and have built a solution that uses
globals
andget/setattr
and thus doesn't need eval. A slight modification is that instead of directly using the packages__path__
forwalk_packages
, I use the packages parent directory and then only import modules starting with__name__ + "."
. This was done to reliably get all subpackages fromwalk_packages
- in my use case I had a subpackage namedtest
which caused pkgutil to iterate over thetest
package from python's library; furthermore, using__path__
would not recurse into the packages subdirectories. All these issues were observed using jython and python2.5, the code below is only tested in jython thus far.Also note that OPs question only talks about importing all modules from a package, this code recursively imports all packages too.
As a future improvement I'll try to make this dynamic with a
__getattr__
hook on the package, so the actual modules are only imported when they are accessed...This is based on the answer that kolypto provided, but his answer does not perform recursive import of packages, whereas this does. Although not required by the main question, I believe recursive import applies and can be very useful in many similar situations. I, for one, found this question when searching on the topic.
This is a nice, clean way of performing the import of the subpackage's modules, and should be portable as well, and it uses the standard lib for python 2.7+ / 3.x.
Usage:
I was writing a small personal library and adding new modules all the time so I wrote a shell script to look for scripts and create the
__init__.py
's. The script is executed just outside of the main directory for my package, pylux.I know it probably isn't the answer you're looking for, but it servered its purpose for me and it might be useful to someone else, too.
I got tired of this problem myself, so I wrote a package called automodinit to fix it. You can get it from http://pypi.python.org/pypi/automodinit/. Usage is like this:
setup.py
dependencies.__init__.py
file:That's it! From now on importing a module will set
__all__
to a list of .py[co] files in the module and will also import each of those files as though you had typed:Therefore the effect of
from M import *
matches exactlyimport M
.automodinit is happy running from inside ZIP archives and is therefore ZIP safe.
In Python 3, you can put the following code in your
scripts.__init__.py
file:For more info about Python imports, I recommend David Beazley's talk at PyCon 2015: https://youtu.be/0oTh1CXRaQ0
Edit: Here's one way to recursively import everything at runtime...
(Contents of
__init__.py
in top package directory)I'm not using
__import__(__path__+'.'+module_name)
here, as it's difficult to properly recursively import packages using it. If you don't have nested sub-packages, and wanted to avoid usingglobals()[module_name]
, though, it's one way to do it.There's probably a better way, but this is the best I can do, anyway.
Original Answer (For context, ignore othwerwise. I misunderstood the question initially):
What does your
scripts/__init__.py
look like? It should be something like:You could even do without defining
__all__
, but things (pydoc, if nothing else) will work more cleanly if you define it, even if it's just a list of what you imported.