1

Possible Duplicate:
Python package structure

Hello, I'm looking to import a python file that I have in a sub-directory that is below the root of my main file. e.g.

import ../library/utils.py

When I put that into my code and run it I get a compile error.

Is there a way to include files from below the main file root directory or does it have to be in a sub-directory in the root?

Thanks for your help.

Community
  • 1
  • 1
Nalum
  • 4,143
  • 5
  • 38
  • 55

2 Answers2

9

You don't import files, you import modules. Modify sys.path accordingly, and do import utils, e.g.

import sys
sys.path.append('../library')
import utils
Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
  • 1
    this will work, but not in a location independent way. – Andrew May 23 '11 at 21:13
  • Why should I only import modules. For instance I got a file called credentials.py which contains the DB credentials I need in a lot of scripts. All scripts use import credentials and access then the variables defined in credentials.py. Is this bad practice? What would be advised? – Hyperboreus May 23 '11 at 21:13
  • @Hyperboreus - take it this way - any file which you import IS a module. And about the practice, well.. I do the same :) – tmg May 23 '11 at 21:18
  • @Hyperboreus: By that I meant that while modules can be loaded from files, the import mechanism is a bit more flexible than that (that's why you use module names with `import`, not file names). – Cat Plus Plus May 23 '11 at 21:19
  • @Hyperboreus: it's not about what you should do (that's another subject matter), but in python the import statement import a **module** opposite to languages like C that includes a file. If you have some file credentials.py, the only thing python allows is to import the credentials module (knowing if it is implemented by the credentials.py file or not is irrelevant). – kriss May 23 '11 at 21:20
  • @Andrew: Example code, `sys.path.append` is more important here. Based on two answers OP can adjust the argument to make it work on their side, I didn't want to obscure the snippet with path manipulation. – Cat Plus Plus May 23 '11 at 21:20
  • You should always avoid modifying sys.path in application code. It's too difficult to do correctly (this answer is incorrect - '../library' is a relative path, and will be interpreted relative to the *current working directory* - which has nothing to do with the location of the source of the utils module). – Jean-Paul Calderone May 23 '11 at 21:21
  • @kriss Then how does my interpreter know that the module credentials is implemented in credentials.py if the file name of the implementing file has nothing to do with the module name? The file is just another py-file in the same folder and does nothing funny. It has only one line saying passwd='mypasswd'. – Hyperboreus May 23 '11 at 21:24
  • @Hyperboreus: I didn't said that the file name has nothing to do with module name. The implementation of modules in python is based on a file naming convention. But from inside python interpreter when you do import credentials it could mean either that the module is implemented by some 'credentials.py' file or that it is implemented by some '`__init__.py`' file inside a 'credentials' directory. From a python program there is no way (at least no easy way that I know of) to tell the difference between both cases. – kriss May 26 '11 at 08:36
3
import sys, os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'library')))

import utils

This will modify the sys.path variable that contains the directories to search for files. It will also make sure that it will find it properly even if you run it as:

$ python the_file.py
$ python ../the_file.py
$ python /somewhere/over/the_file.py

This will work for stuff under development, testing, training. Installed files will not need such a construct.

Andrew
  • 2,530
  • 16
  • 9
  • This is slightly less incorrect than Cat's answer because it tries to compute the correct absolute path to add to sys.path instead of assuming that process working directory will be the same as the base of the Python package. However, it's still incorrect because `__file__` may not reflect the actual installed location of the source (bytecode is often built in a temporary build directory and then relocated to an installation directory). It also fails for eggs and zip files. – Jean-Paul Calderone May 23 '11 at 21:22
  • 2
    wow, your 100% solution stands to be pretty cool then! – Andrew May 23 '11 at 21:27
  • just use a buildout with some zc.recipe.egg to prepare correct pathes :-) ... may be a bit of overkill. – kriss May 26 '11 at 08:44