Absolute/relative 在 Python 中导入:ModuleNotFoundError 等等

Absolute/relative import in Python: ModuleNotFoundError and more

这是我的项目结构:

- config
- data
- src
    - resources 
    - db
- test

N.B.: 我正在使用 Python 3.9,每个包含 .py 文件的文件夹也有一个 __init__.py 文件

我想要 运行 的所有脚本都位于 /src 文件夹中,它们使用了放置在 /src/resources 文件夹(基本上就像一个库)中的其他脚本的代码。 其中一些脚本还从 /config 文件夹中读取 YAML 文件

这就是问题所在,我找不到从命令行正确 运行 这些脚本的方法,我总是收到如下错误:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/runpy.py", line 185, in _run_module_as_main
    mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
  File "/usr/local/lib/python3.8/runpy.py", line 111, in _get_module_details
    __import__(pkg_name)
  File "/home/pi/crypto/src/ethMessage.py", line 4, in <module>
    import update_db
  File "/home/pi/crypto/src/update_db.py", line 1, in <module>
    from db.mysql_main import insertValueAndFee
  File "/home/pi/crypto/src/db/mysql_main.py", line 6, in <module>
    from src.resources.parser import read_yaml
ModuleNotFoundError: No module named 'src'

我尝试了相对导入和绝对导入,现在我正在使用绝对导入(例如 from src.resources.parser import read_yaml)

从命令行 运行 脚本的正确方法是什么?

编辑:

按照你的建议,我添加了

sys.path.append( os.path.abspath(os.path.dirname(__file__)+'/..') )

所有主要脚本,我仍然收到类似的错误:

Traceback (most recent call last):
  File "src/ethMessage.py", line 6, in <module>
    import update_db
  File "/home/pi/crypto/src/update_db.py", line 1, in <module>
    from db.mysql_main import insertValueAndFee
  File "/home/pi/crypto/src/db/mysql_main.py", line 6, in <module>
    from src.resources.parser import read_yaml
ModuleNotFoundError: No module named 'src'

澄清一下,我运行正在从全局文件夹中创建我的脚本,在我的例子中,它被命名为“crypto”。 我也愿意用不会产生问题的方式更改项目结构。

如果您想通过根名称引用所有这些包,那么您只需将该文件夹添加到 Python 路径即可。所以,对于 src 中的主程序脚本,只需添加如下内容:

import os
import sys
sys.path.append( os.path.abspath(os.path.dirname(__file__)+'/..') )

现在,无论您 运行 它来自何处,脚本的父目录都将位于路径中。现在你可以说

from src.resources.parser import read_yaml

如果有人仍在寻找解决方案,我强烈建议不要理会 Python 的导入:它们可能是整个语言中最糟糕的部分。

相反,如果您想将某些文件用作库,则应使用 setuptools 从这些文件创建包。

然后,您可以在本地安装它,也可以在 PyPi 上发布它。

通过这种方式,您可以像导入另一个第三方模块(例如请求、selenium 等)一样在脚本中导入您的库,一切都会正常进行,而不是让您头疼,因为文件是在一个目录而不是另一个目录中。