Search code examples
pythonpackagedirectory-structurerelative-import

Python Relative Import cannot find package


I'm sure that this is a pretty simple problem and that I am just missing something incredibly obvious, but the answer to this predicament has eluded me for several hours now.

My project directory structure looks like this:

-PhysicsMaterial
   -Macros
      __init__.py
      Macros.py
   -Modules
      __init__.py
      AvgAccel.py
      AvgVelocity.py
   -UnitTests
      __init__.py
      AvgAccelUnitTest.py
      AvgVelocityUnitTest.py
    __init__.py

Criticisms aside on my naming conventions and directory structure here, I cannot seem to be able to use relative imports. I'm attempting to relative import a Module file to be tested in AvgAccelUnitTest.py:

from .Modules import AvgAccel as accel

However, I keep getting:

ValueError: Attempted relative import in non-package

Since I have all of my init files set up throughout my structure, and I also have the top directory added to my PYTHONPATH, I am stumped. Why is python not interpreting the package and importing the file correctly?


Solution

  • This occurs because you're running the script as __main__. When you run a script like this:

    python /path/to/package/module.py
    

    That file is loaded as __main__, not as package.module, so it can't do relative imports because it isn't part of a package.

    This can lead to strange errors where a class defined in your script gets defined twice, once as __main__.Class and again as package.module.Class, which can cause isinstance checks to fail and similar oddities. Because of this, you generally shouldn't run your modules directly.

    For your tests, you can remove the __init__.py inside the tests directory and just use absolute instead of relative imports. In fact, your tests probably shouldn't be inside your package at all.

    Alternatively, you could create a test runner script that imports your tests and runs them.