5
my_project
    -my_project
        - __init__.py
        - main.py
        - constants.py
        -test
            - __init__.py
            - test_main.py

test_main.py from my_project import main

main.py import constants

When I run nosetests in my_project, I end up getting ImportError: No module named 'constants'

Both __init__.py files are blank.

If I change import constants to from my_project import constants in main.py, nosetests work. However, now if I just run python main.py I get ImportError: No module named 'my_project'.

Can someone help me point out what I'm doing wrong? I've searched quite a few posts but I haven't been able to fix it myself. Thanks.

koreebay
  • 149
  • 9
  • If you're not running from my_project (or its parent directory), then you need to tell Python where to look for your module. You can add your my_project path to `sys.path` to force it to look there. – Tom Karzes Nov 17 '15 at 18:17
  • I see, but I am running `nosetests` from my_project (parent directory) and I've also tried running it in the other my_project (child) directory as well. In both cases, I end up getting `ImportError: No module named 'constants'`. – koreebay Nov 17 '15 at 18:28

2 Answers2

3

In main.py -> import constants is an implicit relative import (bad). It should be changed to the more usual from my_project import constants.

You mentioned this makes nosetests work. Note: you don't need the __init__.py in the tests sub-directory, and in fact this is usually discouraged.

Now to fix your error with python main.py having an import error, well that is normal if you haven't included it in your sys.path. There are various ways around this -

  • execute from the project root directory (i.e. the uppermost my_project one)
  • set the PYTHONPATH environment variable
  • properly package and install your app using setuptools / easy_install etc
wim
  • 338,267
  • 99
  • 616
  • 750
  • Thank you. I will avoid implicit relative imports and remove `__init__.py`from the tests sub-directory. It seems like executing from the project root directory still doesn't solve the problem. I think this is explained by [Evert's answer](http://stackoverflow.com/a/33767277/5573312), but I'll look into it more. – koreebay Nov 17 '15 at 23:38
2

You're attempting a relative import in Python 2 style in a Python 3 project: import constants will, in Python 3, attempt to import constants at the main sys.path level.

Instead, use something like

from . import constants

in main.py

See for example PEP 404:

In Python 3, implicit relative imports within packages are no longer available - only absolute imports and explicit relative imports are supported.

and this SO question.

Community
  • 1
  • 1
  • Thank you. As I am relatively new at this, I did not know Python 3 does not allow implicit relative imports. I will take your suggestion into consideration and will look through your provided link. – koreebay Nov 17 '15 at 23:40