Python imports when scripts are run from different folder (ancestor)

断了今生、忘了曾经 提交于 2020-06-28 04:56:32

问题


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

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:

  1. Identify clearly what you want your top level modules and packages to be.

  2. Make all imports absolute.

  3. 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.
  4. Make sure to call your code via the executable module method instead of the script method

    • path/to/pythonX.Y -m toplevelpackage.module DO
    • path/to/pythonX.Y toplevelpackage/module.py DON'T
    • path/to/pythonX.Y -m toplevelmodule DO
    • path/to/pythonX.Y toplevelmodule.py DON'T
    • path/to/pythonX.Y -m toplevelpackage.subpackage DO (assuming there is toplevelpackage/subpackage/__main__.py file)
  5. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!