Python 3中的相对导入不起作用

2024-05-07 07:31:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下目录:

mydirectory
├── __init__.py
├── file1.py 
└── file2.py

我在file1.py中定义了一个函数f。

如果,在file2.py中,我是

from .file1 import f

我得到以下错误:

SystemError: Parent module '' not loaded, cannot perform relative import

为什么?如何让它发挥作用?


Tags: 函数frompyimport目录定义init错误
3条回答

在包中以可执行文件的形式启动模块是一种不好的做法。

当你开发某个东西时,你要么构建一个库,这个库将被其他程序导入,因此允许直接执行它的子模块没有多大意义,要么构建一个可执行文件,在这种情况下,没有理由让它成为包的一部分。

这就是在setup.py中区分包和脚本的原因。程序包将位于site-packages下,而脚本将安装在/usr/bin(或类似的位置,具体取决于操作系统)。

因此,我建议使用以下布局:

/
├── mydirectory
|    ├── __init__.py
|    ├── file1.py 
└── file2.py

其中,file2.pyfile1.py作为任何其他希望使用库的代码导入,mydirectory,并使用绝对导入

from mydirectory.file1 import f

当您为项目编写setup.py脚本时,您只需将mydirectory作为包和file2.py作为脚本列出,一切都将正常工作。不需要摆弄sys.path

如果出于某种原因,您确实希望运行包的子模块,那么正确的方法是使用-m开关:

python -m mydirectory.file1

这将加载整个包,然后将模块作为脚本执行,从而允许相对导入成功。

我个人不会这么做。也因为很多人甚至不知道你能做到这一点,最终会得到与你相同的错误,并认为包是坏的。


关于当前接受的答案,它说您应该只使用一个隐式相对导入from file1 import f,因为它将工作,因为它们在同一目录中:

这是错误的!

  • 它不会在python3中工作,在python3中不允许隐式相对导入,如果您碰巧安装了file1模块(因为它将被导入而不是您的模块!),它肯定会崩溃。
  • 即使它起作用,file1也不会被视为mydirectory包的一部分。这个可以物质。

    例如,如果file1使用pickle,则包的名称对于正确加载/卸载数据非常重要。

在启动python源文件时,禁止使用相对导入来导入另一个文件(即当前包中的文件)。

documentation中说:

注意,相对导入基于当前模块的名称。由于主模块的名称始终为“\uu main\uu”,因此用作Python应用程序主模块的模块必须始终使用绝对导入。

所以,正如@mrKelley所说,在这种情况下需要使用绝对导入。

由于file1file2位于同一目录中,您甚至不需要有__init__.py文件。如果你想扩大规模,那就把它留在那里。

要在同一目录的文件中导入某些内容,请执行以下操作

from file1 import f

也就是说,不需要执行相对路径.file1,因为它们在同一个目录中。

如果运行整个应用程序的主函数、脚本或其他东西位于另一个目录中,则必须使所有内容都与正在执行的位置相关。

相关问题 更多 >