2

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?

S. Gamgee
  • 501
  • 5
  • 16

2 Answers2

3

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.

Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
  • @ Brendan Abel Thanks for the information. After doing a bit more research, I came to the exact same conclusion: ultimately, I ended up using sys.path.append and performing absolute imports. It shouldn't bother me further as I do not intend to be relocating modules within the directory. This actually also solves another import problem involving a function decorator that I needed, so that's two thumbs up! – S. Gamgee Jul 28 '16 at 20:36
  • You may still run into issues if other modules import the same module you're running on the command line. – Brendan Abel Jul 28 '16 at 20:38
  • I guess I'll cross that bridge when I come to it. I'm sure by then, I'll have a better solution. This is merely a hobby program with little to no intent to ship, so I think it will turn out alright – S. Gamgee Jul 28 '16 at 20:40
0

How to fix "Attempted relative import in non-package" even with __init__.py

Well, guess it's on to using sys.path.append now. Clap and a half to @BrenBarn, @fireant, and @Ignacio Vazquez-Abrams

Community
  • 1
  • 1
S. Gamgee
  • 501
  • 5
  • 16