问题
I have a large repository with some fixed structure and I have extended it by some folders and python scripts to add extra functionality to it as a whole. The structure looks as follows:
- toplevelfolder
- featureA
- someModuleA.py
- __ init __.py
- featureB
- someModuleB.py
- __ init __.py
- application
- __ init __.py
- app.py
- featureA
Now someModuleA.py
and someModuleB.py
can be invoked via app.py
but at the same time also have be able to be invoked directly, however this invocation must come from the toplevelfolder for the relative paths in the file to resolve correctly, i.e. via python ./featureA/someModuleA.py
.
This all works well, but now I need some function definitions from someModuleB
in someModuleA
and hence I want to import this module. I have tried both absolute and relative imports, but both fail with different errors, the absolute import with
from toplevelfolder.featureA import someModuleA as A
# ModuleNotFoundError: No module named 'toplevelfolder'
and the relative import with
from toplevelfolder.featureA import someModuleA as A
# ImportError: attempted relative import with no known parent package
Now I can see that the relative import would cause problems when python is invoked from the toplevelfolder
, as ..
would represent the latter's parent directory, rather than the parent directory of featureA
. However, I cannot get a hold of the first error message, especially since toplevelfolder
should not be a module but a package.
Is there another way to import in Python that I'm not aware of, if possibly without modifying PYTHONPATH or sys.path or something like that?
回答1:
Not 100% sure on what the goal is here. My advice would be:
Identify clearly what you want your top level modules and packages to be.
Make all imports absolute.
Either:
- make your project a real installable project, so that those top level modules and packages are installed in the environment's
site-packages
directory; - or make sure that the current working directory is the one containing the top level modules and packages.
- make your project a real installable project, so that those top level modules and packages are installed in the environment's
Make sure to call your code via the executable module method instead of the script method
path/to/pythonX.Y -m toplevelpackage.module
DOpath/to/pythonX.Y toplevelpackage/module.py
DON'Tpath/to/pythonX.Y -m toplevelmodule
DOpath/to/pythonX.Y toplevelmodule.py
DON'Tpath/to/pythonX.Y -m toplevelpackage.subpackage
DO (assuming there istoplevelpackage/subpackage/__main__.py
file)
Later on, once it all works well and everything is under control, you might decide to change some or all imports to relative. (If things are done right, I believe it could be possible to make it so that it is possible to call the executable modules from any level within the directory structure as the current working directory.)
References:
- Old reference, possibly outdated, but assuming I interpreted it right, it says that running scripts that live in a package is an anti pattern, and one should use
python -m package.module
instead: https://mail.python.org/pipermail/python-3000/2007-April/006793.html -- https://www.python.org/dev/peps/pep-3122/
回答2:
Try pasting this above your import:
import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)
Then you should be able to import a file from the parent-folder.
来源:https://stackoverflow.com/questions/61680185/python-imports-when-scripts-are-run-from-different-folder-ancestor