【问题标题】:Relative import problem with python packagespython包的相对导入问题
【发布时间】:2021-04-05 03:14:42
【问题描述】:

首先,我浏览了很多关于这个问题的问答,但我找不到我的问题的解决方案。


我使用的是 Python 3.7.9,我的文件结构如下所示

generator/
    __init__.py
    main.py
    summarygenerator/
        __init__.py
        utils.py
        summary_generator.py

summary_generator.py 看起来像

from summarygenerator.utils import solver

def sum_gen():
   pass
if __name__ == '__main__':
   sum_gen()

通过这种方法,我可以从“generator”目录运行 main.py:

python main.py

和 summary_generator.py 一起

python -m summarygenerator.summary_generator

但是,当我想从 generator/summarygenerator 目录运行 summary_generator.py 时,我会遇到:

ModuleNotFoundError: No module named summarygenerator

如下所示的相对导入也不能解决问题。

from .utils import solver

【问题讨论】:

  • 在 utils 和 summarygenerator 的顶部添加以下代码并尝试:import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '../')) 然后像您已经完成的那样导入模块from summarygenerator.utils import solver
  • 这其实是个很不好的习惯,像这样修改系统路径可能会导致各种问题。最好附加到 PYTHONPATH 变量。
  • 你试过from generator.summarygenerator.utils import solver吗?您看到的部分成功是当前目录始终被认为位于 Python 路径上。所以它“看到”summarygenerator 模块,但没有别的。整个目录甚至在 Python 路径上吗?你可以在任何地方import generator 吗?

标签: python python-3.x python-import relative-import


【解决方案1】:

Python 模块应从其根目录的父目录运行 包裹。所以运行脚本的正确方法是(从生成器目录开始):

$ cd ..
$ python -m generator.main
$ python -m generator.summarygenerator.summary_generator

导入是开箱即用的,您甚至可以使用相对导入。现在您似乎希望能够在开箱即用的两个不同位置(使用相同的代码)使用相同的代码运行 python 脚本。这不受支持,而且确实没有意义。在导入的情况下,这意味着 python 应该能够以 两种 不同的方式记录模块的名称,并且所有东西(所有其他模块名称)都应该使用这两个名称。或者采取(更简单)在文件中定义相对路径的情况(如open('some_file')) - 如果文件以两种方式运行,这注定要失败。在这两种情况下,问题都是当前工作目录的变化——运行脚本的目录被设置为当前工作目录,相对于计算路径(包括模块路径)。您可以通过弄乱当前的工作目录并创建更微妙的错误来使“从任何文件夹运行我”工作 - 或者(这是我认为的答案)停止尝试能够从不同的文件夹运行相同的脚本,编写导入,以便它们使用上面的命令,这是运行 python 脚本的推荐方式(因此所有关于导入的文档都假定这种运行方式)

【讨论】:

    【解决方案2】:

    所以,这个错误很明显,因为您没有声明一个名为 summarygenerator 的模块。由于utilssummary_generator 代码位于同一模块中,因此您可以尝试像下面这样直接导入,因为Python's module search path starts with the current directory

    from utils import solver
    

    解决您的问题的其他方法(通常是当 utils 位于不同的模块中时)是打包您的应用程序并显式声明您的模块,或者查看设置 PYTHONPATH 以包含您想要的模块。

    【讨论】:

    • 其实你的建议是行不通的(照常直接导入)。使用这种方法,当您从外部目录调用包时,它找不到“utils”并会抛出“ModuleNotFoundError”。
    • 啊,我明白了。没有意识到您也想从外部目录中调用它。在这种情况下,我会说,要么考虑打包它,因为它是一个命令行工具。否则,PYTHONPATH 是您的最佳路线。
    猜你喜欢
    • 1970-01-01
    • 2019-03-17
    • 2012-04-20
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多