I have a Python package with several subpackages.
myproject/
__init__.py
models/
__init__.py
...
controllers/
__init__.py
..
scripts/
__init__.py
myscript.py
Within myproject.scripts.myscript, how can I access myproject.models? I’ve tried
from myproject import models # No module named myproject
import models # No module named models
from .. import models # Attempted relative import in non-package
I’ve had to solve this before, but I can never remember how it’s supposed to be done. It’s just not intuitive to me.
This is the correct version:
If it fails with
ImportError: No module named fooit is because you haven’t setPYTHONPATHto include the directory which containsmyproject/.I’m afraid other people will suggest tricks to let you avoid setting
PYTHONPATH. I urge you to disregard them. This is whyPYTHONPATHexists: to tell Python where to look for code to load. It is robust, reasonably well documented, and portable to many environments. Tricks people play to avoid having to set it are none of these things.The explicit relative import will work even without
PYTHONPATHbeing set, since it can just walk up the directory hierarchy until it finds the right place, it doesn’t need to find the top and then walk down. However, it doesn’t work in a script you pass as a command line argument topython(or equivalently, invoke directly with a#!/usr/bin/pythonline). This is because in both these cases, it becomes the__main__module of the process. There’s nowhere to walk up to from__main__– it’s already at the top! If you invoke the code in your script by importing that module, then it will be fine. That is, compare:to
You can take advantage of this by not executing your script module directly, but creating a
bin/myscriptthat does the import and perhaps calls a main function:Compare to how Twisted’s command line scripts are defined: http://twistedmatrix.com/trac/browser/trunk/bin/twistd