📅  最后修改于: 2023-12-03 15:04:16.275000             🧑  作者: Mango
在Python中,当需要从一个模块中导入另外一个模块时,我们通常使用import
语句,例如:
from package1.module1 import func1
但是,如果我们的模块文件在一个包文件夹中,而需要从这个包文件夹的上层目录中导入模块,应该怎么做呢?本文将介绍几种方法来解决这个问题。
Python有一个名为sys.path
的列表,它包含Python解释器查找模块的路径。默认情况下,sys.path
中包含了Python解释器搜索的一些默认路径,例如Python标准库,当前目录等等。
我们可以通过将上层目录的路径添加到sys.path
中来使Python解释器能够找到我们要导入的模块。假设我们当前的工作目录是项目的根目录,而我们需要从package1/module1.py
中导入func1()
,那么可以在module2.py
中这样写:
import sys
sys.path.append("..") # 将上层目录添加到sys.path中
from package1.module1 import func1
这个方法虽然简单,但是有一些缺点。首先,需要手动将路径添加到sys.path
中,容易出错。其次,如果我们从多个地方导入同一个模块,需要在每一个地方都加上路径设置,这样就会重复劳动。
Python3中推荐使用绝对导入,它可以解决方法一所提到的两个问题。根据Python的PEP 328,在绝对导入中,从包中导入模块时,需要使用绝对路径。
在Python中,我们可以通过from
关键字后面的.
来指定一个包中的子包或模块。例如,如果我们需要从package1/submodule1.py
中导入func1()
,可以这样写:
from .submodule1 import func1
在这个例子中,.
表示当前包(即package1
),所以我们可以使用相对路径来引用子包或模块。
在使用绝对导入时,我们需要做一些设置,以便让解释器知道我们要从哪里搜索模块。在包文件夹中,我们通常会有一个名为__init__.py
的文件,它会在包被导入时执行。因此,我们可以在这个文件中设置Python的搜索路径。
假设我们的目录结构如下:
myproject/
package1/
__init__.py
submodule1.py
module2.py
我们可以在package1/__init__.py
中这样写:
import os
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
这个代码会将上层目录的绝对路径添加到sys.path
中,从而使我们能够从上层目录中导入模块。现在,我们可以在module2.py
中这样写:
from package1.submodule1 import func1
这个方法需要在包文件夹中做一些设置,但是更好地遵守了Python3的推荐规范。
如果我们的项目依赖于一个包管理器,例如pip、setuptools等等,那么可以使用一个名为pkg_resources
的包来导入上层目录中的模块。
pkg_resources
提供了一个require()
函数,它可以从指定的位置导入一个模块。我们可以使用下面的代码导入上层目录中的module1.py
:
from pkg_resources import require
require('../module1.py')
这样做的好处是,不需要手动设置Python的搜索路径,而且不会重复地导入同一个模块。但是,这个方法需要项目使用了包管理器,否则会出现找不到包的错误。
在使用上述三种方法时,需要格外注意代码的结构和文件路径。在Python中,包的导入关系和文件的层次结构有着紧密的关系,因此必须遵循一定的规范。