Import parent directory for brief tests

Rig picture Rig · Jul 12, 2012 · Viewed 7.7k times · Source

I have searched this site top to bottom yet have not found a single way to actually accomplish what I want in Python3x. This is a simple toy app so I figured I could write some simple test cases in asserts and call it a day. It does generate reports and such so I would like to make sure my code doesn't do anything wonky upon changes.

My current directory structure is: (only relevant parts included)

project
  -model
     __init__.py
     my_file.py
     -test
       my_file_test.py

I am having a hell of a time getting my_file_test.py to import my_file.py.

Like I've said. I've searched this site top to bottom and no solution has worked. My version of Python is 3.2.3 running on Fedora 17.

Previously tried attempts: https://stackoverflow.com/questions/5078590/dynamic-imports-relative-imports-in-python-3 Importing modules from parent folder Can anyone explain python's relative imports? How to accomplish relative import in python

In virtually every attempt I get an error to the effect of:

ImportError: No module named * OR ValueError: Attempted relative import in non-package

What is going on here. I have tried every accepted answer on SO as well as all over the interwebs. Not doing anything that fancy here but as a .NET/Java/Ruby programmer this is proving to be the absolute definition of intuitiveness.

EDIT: If it matters I tried loading the class that I am trying to import in the REPL and I get the following:

>>> import datafileclass
>>> datafileclass.methods
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
>>> x = datafileclass('sample_data/sample_input.csv')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'module' object is not callable

If it matters...I know the functionality in the class works but I can't import it which in the now is causing an inability to test. In the future will certainly cause integration issues. (names changed to protect the innocent) getting within a couple of weeks of desired functionality for this iteration of the library...any help could be useful. Would have done it in Ruby but the client wants the Python as a learning experience,

Answer

ecatmur picture ecatmur · Jul 12, 2012

Structure your code like this:

project
  -model
    __init__.py
    my_file.py
  -tests
    __init__.py
    test_my_file.py

Importantly, your tests directory should also be a module directory (have an empty __init__.py file in it).

Then in test_my_file.py use from model import my_file, and from the top directory run python -m tests.test_my_file. This is invoking test_my_file as a module, which results in Python setting up its import path to include your top level.

Even better, you can use pytest or nose, and running py.test will pick up the tests automatically.

I realise this doesn't answer your question, but it's going to be a lot easier for you to work with Python standard practices rather than against them. That means structuring your project with tests in their own top-level directory.