from app.util.File import loadDataFromPickle
is an absolute import, meaning
- go to
sys.path
- from any of the paths listed there
- find the first one that has an
app
module.
- Then import the
util
module from that app
module.
- ...
The tricky bit is the sys.path
, which is documented as
As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.
So if you run Foo/app/tests/test_gram.py
, sys.path
starts with .../Foo/app/tests/
. There's no app
module anywhere below that directory, so you cannot import app
using an absolute import (unless there's an app
somewhere else on some sys.path
).
As suggested in the comments and other answers, it is good practice to use relative imports in such situations:
from ..util.File import loadDataFromPickle
Relative imports are relative to the current package/module, not to the directories in sys.path
.
Edit:
However, relative imports will not work when running the script directly from the command line, as python will complain that the ''
module has not been imported (Parent module '' not loaded, cannot perform relative importSystemError: Parent module ''
). Well, that's because the parent modules (tests
and ''
) are not loaded when running the script directly and the importer rightly assumes they should be.
One trick is to run the test script as a module:
python -m app.tests.test_gram.py
This will most likely require some changes to the test script, at least having
if __name__ == '__main__':
[...]
inside the script. See also Relative imports in Python 3 for more details.
As a suggestion, you might want to convert the test script to using unittest
, anyway.