mehulkar
mehulkar

Reputation: 4974

Importing modules from parent directory in Python 2.7

I'm failing to import a module from a parent directory in 2.7 and I'm not sure why. Any help would be appreciated.

Directory Structure

I have a Python package with this directory structure:

source/
|--foo/__init__.py
|--foo/bar/__init__.py
|--foo/bar/nested.py
|--foo/top.py
tests/
|--helpers/__init__.py
|--foo/__init__.py
|--foo/bar/__init__.py
|--foo/bar/nested_test.py
|--foo/top_test.py
setup.py
setup.cfg
tox.ini

Configuration

I use pytest and python setup.py test almost interchangeably to run my tests with. In tox.ini, I have:

[tox]
envlist = py27

[testenv]
commands = pytest
deps = pytest

[pytest]
testpaths=tests

Note, that I don't actually use tox to run my tests.

And in setup.cfg:

[aliases]
test=pytest

I'm not 100% sure, but I think this setup means that when I run python setup.py test, it actually just runs pytest, so it might not be relevant to this question.

Question

In foo/top_test.py, I can import tests.helpers, but in foo/bar/nested_test.py, the same import raises an ImportError saying that the module was not found.

Why is this and how can I fix it?

Attempts

I've attempted to run pytest and python setup.py test in a clean virtualenv after running pip install pytest and pip install -r requirements.txt (My requirements.txt is basically a blank file with -e and -i set to a private repo.

Note: I can open up a python REPL from the root directory of the project and import tests._helper without any problems.

I've also attempted to add tests and tests.helpers to the tests_require argument in the setuptools.setup() function in setup.py, but it looks like it attempts to install those from the remote index instead of using the local modules.

I've also attempted appending to sys.path in my foo/bar/nested_test.py:

import os
import sys

sys.path.append(os.path.realpath('tests'))

Other notes

Upvotes: 2

Views: 727

Answers (1)

jq170727
jq170727

Reputation: 14655

One thing I notice is you don't appear to have a tests/__init__.py. Not sure if that matters in your case but it does in the example below.

Whenever I have a problem like this I try and setup a simplified test case with as few things as possible. Get setuptools, pytest and all that other noise out of the way and just debug the module structure and then add those back after you know your structure is sound.

For example, here's a script

#!/bin/bash
rm -rf tests
mkdir -p tests/foo/bar
mkdir -p tests/helpers
touch tests/__init__.py
touch tests/foo/__init__.py
touch tests/foo/bar/__init__.py
touch tests/helpers/__init__.py
echo 'import tests.helpers' > tests/foo/top_test.py
echo 'import tests.helpers' > tests/foo/bar/nested_test.py
tree tests
python -c 'import tests.foo.bar.nested_test; print "got here"'

which produces the output

tests
|-- __init__.py
|-- foo
|   |-- __init__.py
|   |-- bar
|   |   |-- __init__.py
|   |   `-- nested_test.py
|   `-- top_test.py
`-- helpers
    `-- __init__.py

3 directories, 6 files
got here

Once you have a simple script like this you can interactively experiment with your imports.

Upvotes: 1

Related Questions