I have an application with a heirarchy of packages. There are a fair number of modules that reference other modules higher up in the package heirarchy. As exemplified below, I can use relative imports to solve this problem. However, running the module directly for testing fails with an Attempted relative import in non-package
exception.
Is there a better way to organize my application or my import statements so that modules can both be executed individually for testing and imported from other modules?
\spam
\morespam
child.py
base.py
\eggs
user.py
base.py
class Base(object):
def hello(self):
print 'Um, wot?'
child.py
from ..base import Base # references the parent package correctly,
# but fails when this module is executed individually
class Child(Base):
def hello(self):
print 'Hello, world!'
if __name__ == '__main__':
import unittest
# ... unit test code ...
user.py
from spam.morespam.child import Child
print Child().hello()
I've found that I can add the following header added to the top of a module that needs to reference modules higher in the hierarchy:
if __name__ == '__main__':
import sys, os
sys.path.append(os.path.abspath(os.path.join(sys.path[0], '..')))
The downside is that I need to add this code all over the place, and it isn't constant: the '..'
relative path varies based on the depth of the package in the hierarchy.
python.exe whatever.py
, though.You need to add __init__.py
as empty files in folders that you'd want to do imports from. Doing this will cause python to treat the directories as packages, allowing you to use them in import statements:
\spam
\morespam
__init__.py
child.py
__init__.py
base.py
\eggs
__init__.py
user.py
Once you do this and establish your PYTHONPATH to the base of this directory, you can then do imports:
base.py:
from morespam.child import Child
from ..eggs import user
While a __init__.py
file only needs to be present, you can also define the variable __ALL__
in this file as a list of modules in that directory that you'd want to import if a script tries to use import *
.
I solved this with PyCharm, which automagically adds my source root to the PYTHONPATH every time it runs my application. As far as I can tell, PyCharm basically does option #2 for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With