I\'m trying to follow PEP 328, with the following directory structure:
pkg/
__init__.py
components/
core.py
__init__.py
tests/
core_test.py
Here's one way which will piss off everyone but work pretty well. In tests run:
ln -s ../components components
Then just import components like you normally would.
If someone is looking for a workaround, I stumbled upon one. Here's a bit of context. I wanted to test out one of the methods I've in a file. When I run it from within
if __name__ == "__main__":
it always complained of the relative imports. I tried to apply the above solutions, but failed to work, since there were many nested files, each with multiple imports.
Here's what I did. I just created a launcher, an external program that would import necessary methods and call them. Though, not a great solution, it works.
You can use from pkg.components.core import GameLoopEvents
, for example I use pycharm, the below is my project structure image, I just import from the root package, then it works:
It depends on how you want to launch your script.
If you want to launch your UnitTest from the command line in a classic way, that is:
python tests/core_test.py
Then, since in this case 'components' and 'tests' are siblings folders, you can import the relative module either using the insert or the append method of the sys.path module. Something like:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
Otherwise, you can launch your script with the '-m' argument (note that in this case, we are talking about a package, and thus you must not give the '.py' extension), that is:
python -m pkg.tests.core_test
In such a case, you can simply use the relative import as you were doing:
from ..components.core import GameLoopEvents
You can finally mix the two approaches, so that your script will work no matter how it is called. For example:
if __name__ == '__main__':
if __package__ is None:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
else:
from ..components.core import GameLoopEvents
Because your code contains if __name__ == "__main__"
, which doesn't be imported as a package, you'd better use sys.path.append()
to solve the problem.
In core_test.py, do the following:
import sys
sys.path.append('../components')
from core import GameLoopEvents