How to fix "Attempted relative import in non-package" even with __init__.py
--
Music by Eric Matyas
https://www.soundimage.org
Track title: Future Grid Looping
--
Chapters
00:00 Question
01:01 Accepted answer (Score 475)
01:15 Answer 2 (Score 683)
02:03 Answer 3 (Score 224)
03:16 Answer 4 (Score 212)
03:35 Thank you
--
Full question
https://stackoverflow.com/questions/1153...
Question links:
[PEP 328]: http://www.python.org/dev/peps/pep-0328/
[relative path not working even with __init__.py]: https://stackoverflow.com/questions/9427...
[Import a module from a relative path]: https://stackoverflow.com/questions/2792...
Answer 1 links:
[Ignacio Vazquez-Abrams's]: https://stackoverflow.com/a/11536794/533...
http://www.python.org/dev/peps/pep-0366/
Answer 2 links:
[launch your UnitTest from the command line]: https://docs.python.org/3/using/cmdline....
[sys.path]: https://docs.python.org/2/library/sys.ht...
[launch your script with the '-m' argument]: https://docs.python.org/2/using/cmdline....
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #package #pythonimport #importerror #init
#avk47
ANSWER 1
Score 688
To elaborate on Ignacio Vazquez-Abrams's answer:
The Python import mechanism works relative to the __name__ of the current file. When you execute a file directly, it doesn't have its usual name, but has "__main__" as its name instead. So relative imports don't work.
You can, as Igancio suggested, execute it using the -m option. If you have a part of your package that is meant to be run as a script, you can also use the __package__ attribute to tell that file what name it's supposed to have in the package hierarchy.
See http://www.python.org/dev/peps/pep-0366/ for details.
ACCEPTED ANSWER
Score 474
Yes. You're not using it as a package.
python -m pkg.tests.core_test
ANSWER 3
Score 233
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
ANSWER 4
Score 214
You can use import components.core directly if you append the current directory to sys.path:
if __name__ == '__main__' and __package__ is None:
from os import sys, path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))