【问题标题】:Absolute/relative import in Python: ModuleNotFoundError and morePython 中的绝对/相对导入:ModuleNotFoundError 等
【发布时间】:2021-07-18 19:02:34
【问题描述】:

这是我的项目结构:

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

注意:我使用的是 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”。 我也愿意用不会产生问题的项目结构来改变项目结构。

【问题讨论】:

  • 取决于您运行脚本的方式。如果您从终端运行,则应从路径中删除 src。如果您通过 IDE 运行,则取决于哪个。
  • 我正在一个 IDE (PyCharm) 上开发它们,它通过将内容根添加到 PYTHONPATH 来使一切正常工作。但是这个解决方案不可移植,当我尝试在 Raspberry Pi 上使用 cron 运行脚本时,它不起作用。
  • 你如何打开你的代码?你只打开 src 文件夹吗?还是全局文件夹?
  • 这两种方式都不起作用。哪一个应该是正确的?
  • 全局应该是。最坏的情况,删除 src 并尝试一下:from resources.parser import read_yml

标签: python python-import importerror project-structure


【解决方案1】:

如果您想通过它们的根名称来引用所有这些包,那么您所要做的就是将该文件夹添加到 Python 路径中。因此,对于 src 中的主程序脚本,只需添加如下内容:

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

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

from src.resources.parser import read_yaml

【讨论】:

  • 我将它添加到脚本和它导入的所有文件中,我收到了类似的错误Traceback (most recent call last): File "ethMessage.py", line 6, in &lt;module&gt; import update_db File "/home/pi/crypto/src/update_db.py", line 1, in &lt;module&gt; from db.mysql_main import insertValueAndFee File "/home/pi/crypto/src/db/mysql_main.py", line 6, in &lt;module&gt; from src.resources.parser import read_yaml 另外,从目录或其他地方调用脚本会改变什么吗?
  • 请将您的新回溯添加到问题中。当您在 cmets 中发帖时,我们看不到换行符。
  • 抱歉,我刚刚编辑了问题
  • 您是否在所有导入之前添加了“sys.path.append”行?
  • 不,我不知道。我会尝试。无论如何,没有其他解决方案吗?必须将其粘贴到每个脚本中看起来不是很“时尚”
【解决方案2】:

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

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

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

这样,您可以像其他第三方模块一样在脚本中导入您的库(例如 requests、selenium、...),一切都会正常工作,而不是因为文件位于目录而不是另一个目录。

【讨论】:

    猜你喜欢
    • 2021-09-23
    • 1970-01-01
    • 2016-10-09
    • 2018-01-08
    • 2016-07-19
    • 2018-05-15
    • 1970-01-01
    • 2019-03-04
    • 2011-05-09
    相关资源
    最近更新 更多