tags:

views:

160

answers:

4

What's the shortest way to import a module from a distant, relative directory?

We've been using this code which isn't too bad except your current working directory has to be the same as the directory as this code's or the relative path breaks, which can be error prone and confusing to users.

import sys
sys.path.append('../../../Path/To/Shared/Code')

This code (I think) fixes that problem but is a lot more to type.

import os,sys
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '../../../Path/To/Shared/Code')))

Is there a shorter way to append the absolute path? The brevity matters because this is going to have to be typed/appear in a lot of our files. (We can't factor it out because then it would be in the shared code and we couldn't get to it. Chicken & egg, bootstrapping, etc.)

Plus it bothers me that we keep blindly appending to sys.path but that would be even more code. I sure wish something in the standard library could help with this.

This will typically appear in script files which are run from the command line. We're running Python 2.6.2.

Edit: The reason we're using relative paths is that we typically have multiple, independent copies of the codebase on our computers. It's important that each copy of the codebase use its own copy of the shared code. So any solution which supports only a single code base (e.g., 'Put it in site-packages.') won't work for us.

Any suggestions? Thank you!

+1  A: 

Any reason you wouldn't want to make your own shared-code dir under site-packages? Then you could just import import shared.code.module...

Crad
maybe a symlink?
Kalmi
We don't like site-packages because we typically have multiple, independent copies of the the codebase on our computers. We'd like each copy of the code to use its copy of the shared code (hence the relative path). That all breaks down with a single site-packages directory.
Jon-Eric
A: 

You have several ways to handle imports, all documented in the Python language manual.

See http://docs.python.org/library/site.html and http://docs.python.org/reference/simple%5Fstmts.html#the-import-statement

  1. Put it in site-packages and have multiple Python installations. You select the installation using the ordinary PATH environment variable.

  2. Put the directory in your PYTHONPATH environment variable. This is a per-individual-person setting, so you can manage to have multiple versions of the codebase this way.

  3. Put the directory in .pth files in your site-packages. You select the installation using the ordinary PATH environment variable.

S.Lott
I think all of these solutions break down if there is more than one copy of the codebase (including shared code) on the machine. (Same problem I commented to Crad.) I've edited my question to explain this point.
Jon-Eric
@Jon Eric: If you use `PYTHONPATH`, Each person has their own private references to their selected version of the codebase.
S.Lott
Is it one installation per person, or several per person? I got the feeling there were many copies, not necessarily many persons.
Lennart Regebro
@Lennart, you are correct. A single user typically has multiple copies of the codebase.
Jon-Eric
+2  A: 

You've explained in a comment why you don't want to install "a single site-packages directory", but what about putting in site-packages a single, tiny module, say jebootstrap.py:

import os, sys

def relative_dir(apath):
  return os.path.realpath(
      os.path.join(os.path.dirname(apath),
      '../../../Path/To/Shared/Code'))

def addpack(apath):
  relative = relative_dir(apath)
  if relative not in sys.path:
    sys.path.append(relative)

Now everywhere in your code you can just have

import jebootstrap
jebootsrap.addpack(__file__)

and all the rest of your shared codebase can remain independent per-installation.

Alex Martelli
It doesn't remove the requirement that the working directory has to be a specific one, though... Although that doesn't seem to be a big problem.But I have to say, that this situation just screams buildout/virtualenv to me.
Lennart Regebro
@Lennart, I had a silly typo, not using the `apath` argument in `relative_dir` -- fixed it now, and you'll see there is NO requirement that working dir be anything in particular -- the `__file__` passed to `addpack` is where the calling module lives, nothing to do w/current working directory. Sure, advanced approaches like `virtualenv` are also possible, but this isn't so much about _development_ as about multiple disconnected _deployments_ (on the same non-development machine) if I read the question correctly.
Alex Martelli
Well, I have to say that I think using virtualenv is way simpler that this, so which is advanced is a matter of taste, I guess. ;) I don't see any reason not to use virtualenv or buildout for deployments. Quite the contrary, deployments is what buildout is made for.
Lennart Regebro
"multiple, independent copies of the codebase" sure sounds like a use case for virtualenv (or buildout) to me. virtualenv is widely used for multiple *deployments*.
Ned Deily
+4  A: 

Since you don't want to install it in site-packages, you should use buildout or virtualenv to create isolated development environments. That solves the problem, and means you don't have to fiddle with sys.path anymore (in fact, because Buildout does exactly that for you).

Lennart Regebro