views:

194

answers:

4

This is a python newbie question:

I have the following directory structure:

test
 -- test_file.py
a
 -- b
   -- module.py    

where test, a and b are folders. Both test and a are on the same level.

module.py has a class called shape, and I want to instantiate an instance of it in test_file.py. How can I do so?

I have tried:

from a.b import module

but I got:

ImportError: No module named a.b
A: 

Add the path of your a folder. Like so:

import sys
sys.path.append('/where/it/is/')

Then import like you tried before.

Noio
This removes the package nature of the contents of the OP's directories and doesn't solve his problem.
Noufal Ibrahim
Not a good way to do this.... better to use __init__.py method given in the other answers.
Frozenskys
+4  A: 

The first thing to do would be to quickly browse the official docs on this.

To make a directory a package, you'll have to add a __init__.py file. This means that you'll have such a file in the a and b directories. Then you can directly do an

import a.b.module

But you'll have to refer to it as a.b.module which is tedious so you can use the as form of the import like so

import a.b.module as mod #shorter name

and refer to it as mod.

Then you can instantiate things inside mod using the regular conventions like mod.shape().

There are a few other subtleties. Please go through the docs for details.

Noufal Ibrahim
I did import a.b.module as mod and added __init__.py for all packages but I'm getting ImportError: No module named a.b.module
khelll
@khell you should run command from the root like python test/test_file.py
systempuntoout
It's `__init__.py`. Not `init.py`. Please check the link in the answer for details.
Noufal Ibrahim
+4  A: 

What you want is a relative import like:

from ..a.b import module

The problem with this is that it doesn't work if you are calling test_file.py as your main module. As stated here:

Note that both explicit and implicit relative imports are based on the name of the current module. Since the name of the main module is always "main", modules intended for use as the main module of a Python application should always use absolute imports.

So, if you want to call test_file.py as your main module, then you should consider changing the structure of your modules and using an absolute import, else just use the relative import from above.

3lectrologos
+1. I didn't notice where he was trying to import from.
Noufal Ibrahim
To the (unknown to me) down-voter: When you down-vote an answer you should leave a comment explaining what's wrong with it, so that whoever reads it (and the author) can be informed about the error...
3lectrologos
I'm getting ValueError: Attempted relative import in non-package
khelll
You obviously are running test_file as your main module. In this case you need to move your caller module to the top-level or set your PYTHOPATH to include the package you are trying to import (see also S.Lott's answer below).
3lectrologos
+2  A: 
  1. The directory a needs to be a package. Add an __init__.py file to make it a package, which is a step up from being a simple directory.

  2. The directory b also needs to be a subpackage of a. Add an __init__.py file.

  3. The directory test should probably also be a package. Hard to say if this is necessary or not. It's usually a good idea for every directory of Python modules to be a formal package.

  4. In order to import, the package needs to be on sys.path; this is built from the PYTHONPATH environment variable. By default the installed site-packages and the current working directory are (effectively) the only two places where a package can be found.

    That means that a must either be installed, or, your current working directory must also be a package one level above a.

    OR, you need to set your PYTHONPATH environment variable to include a.

http://docs.python.org/tutorial/modules.html#the-module-search-path

http://docs.python.org/using/cmdline.html#envvar-PYTHONPATH

Also, http://docs.python.org/library/site.html for complete information on how sys.path is built.

S.Lott