Don’t. They are tempting, but they are a really big mess. Let’s start by figuring out what you’re really trying to accomplish. Let’s start with a directory structure.
/Grand- Tophat - settings.py global_entry_point.py package_1- module_1_foo.py module_1_bar.py package_2- module_2_bof.py module_2_baz.py Other_project- random_module.py
The most common reason for wanting relative imports is so that you can
run python Tophat/package_2/module_2_bof.py
from anywhere on your
filesystem. If module_2_bof.py
is self contained, this will work, but
if package_2/module_2_bof.py
depends on package_1/module_1_foo.py
you have a problem. This is where you would want to have a relative
import, in package_2/module_2_bof.py
, an import like this:
from ..package_1.module_1_foo import key_function
There are ways to do this in python, but they are more trouble than they are worth.
What you want to do is control your PYTHONPATH
variable, and add
Tophat
to it. Then you can always do absolute imports relative to
Tophat
. You can add the following line to your .bashrc
to
accomplish this.
PYTHONPATH=$PYTHONPATH:/Grand/Tophat
Ahh, glad you asked. Here is the command you want to run:
cd /Grand/Tophat
add2virtualenv `pwd`
The add2virtualenv command adds a directory to a given virtualenv’s
PYTHONPATH
. From now on, every time you workon
that virtualenv,
the Tophat dir will be in your PYTHONPATH and you won’t have to worry
about relative imports.
Most projects move towards having a global_entry_point.py file that
gets the path setup properly. In django this is manage.py
.
To add the equivalent of globally available scripts to django, you add
management commands, you can then run by
python django_root/manage.py my_command
. This works well for
django management commands which come in separate apps and can’t
assume anything about your environment. The global entry point
approach also has the advantage of a strict order of operations,
ensuring things like the ORM are properly setup. They have the
downside of tying you tightly to whatever framework you are using,
remaining framework agnostic can be an uphill battle and you should
decide what the best fit for you is.
Distutils uses scripts, this is fine for site-packages installed projects, but awkward for scripts that you want to develop on.
Ok, there’s your foot, here’s your shotgun. The best system for relative imports that I have seen is Rocky Bernstein’s pyimport-relative library. This library needs to be globally installed though, so you’ll run into a bit of a chicken and egg situation.