问题
I have a package with the following structure
projectX
├── data
├── results
└── projectX
├── stats
│ ├── __init__.py
│ ├── stats_worker.py
│ └── stats_wroker2.py
├── __init__.py
├── main_worker.py
└── interface.py
Notice that the project folder and the source folder share the same name (projectX).
The problem is a bit complex and needs some premises to be done
Premises:
I always launch the interface and always have launched the interface. No other script is called
My problem first arose when trying to import main_worker from stats_worker2.
I couldn't make it work as a relative import. So I tried to append the parent directory to the sys.path, both from stats_worker2 and from the interface (separately). I tried various ways that I don't remember.
It finally worked by adding the following lines to stats_worker2
sys.path.append('../projectX')
from projectX import main_worker
Now the weirdness starts
After calling the script a couple of times (I don't remember exactly how many), the above sintax doesn't work anymore. Because there is an: ImportError: No module named projectX
EDIT: the above part in italic was due to the fact that I was missing an __init__.py
in the projectX source folder. All other symptoms are still there.
But, weird enough, I can now import successfully the main worker from the stats_worker2 with:
import main_worker
Without any directory being appended to sys.path!
However, Sphinx doesn't work anymore! Specifically, it fails to import all of the modules of the projectX package.
Bonus weirdnessI used to successfully import stats_worker from the interface, now I still can import it, but my IDE (Pycharm) marks that import as unused. It is actually used and if I comment the import, the interface crashes as it is expected to (I already have invalidated Pycharm cache)
回答1:
- Add an empty
__init__.py
file into the source root†. - Your runtime environment will need to be setup so that the project root†† is visible in
sys.path
. The project root should not have an__init__.py
. It isn't necessary for the project directory name to match the package name, but that doesn't really harm anything either. - Remove any
sys.path.append
stuff from python source files, and don't ever do that again. from projectX import main_worker
is a correct import statement for thestats_worker2.py
module. Don't useimport main_worker
.
For step 2, the usual way to do this is via "installing" your package, with python setup.py develop
. i.e. you need to write a setup.py
. Since you apparently don't have a setup.py
, as a cheap workaround you can export PYTHONPATH=<absolute_path_to_project_root>
instead.
†Source root is the deeper projectX
dir, it's the same directory which contains the main_worker.py
module.
††Project root is the shallow projectX
dir, it's the same directory which contains data
and results
subdirectories.
来源:https://stackoverflow.com/questions/42010595/python-weird-import-behaviour