The problem
I've found dozens of articles and tutorials about the basics of using import in Python, but none that would provide a comprehensive guide on setting up your own Python project with multiple packages.
This is my project's structure:
codename/__init__.pypackage1.py(hasclass1and is a script)package2.py(hasclass2)package3.py(hasfunction1and is a script)
test/__init__.pytest_package1.py(has unit tests forpackage1)test_package3.py(has unit tests forpackage3)
How do I setup my imports to have the following requirements met (and do all of them make sense?):
class1,class2andfunction1are in namespacecodename, i.e. this works:import codename obj = codename.class1() codename.function1(obj)they may be imported the same way using
from codename import *orfrom codename import class1function1can easily accessclass1(how?)package1andpackage2are executable scripts- so are
test_package1.pyandtest_package3.py - tests are also executable via
python -m unittest discover - scripts are also executable via
python -m codename.package1
For some reasons I'm having issues with having all of these met and when I try to fix one issue, another one pops out.
What have I tried?
- Leaving
codename/__init__.pyempty satisfies almost all of the requirements, because everything works, but leaves names likeclass1in their module's namespaces - whereas I want them imported into the package. Adding
from codename.package1 import class1et al again satisfies most of the requirements, but I get a warning when executing the script viapython -m codename.package1:RuntimeWarning: 'codename.package2' found in sys.modules \ after import of package 'codename', but prior to execution of \ 'codename.package2'; this may result in unpredictable behaviour
which sort of makes sense...
Running the script via python codename/package1.py functions, but I guess I would probably like both ways to work.
- I ran into an answer to a similar question that stated that internal modules should not also be scripts, but I don't understand why we get the
-mswitch then? Anyway, extracting themains into an externalscriptsdirectory works, but is it the only canonical way of setting all of this up?