报错信息
ImportError: attempted relative import with no known parent package
问题描述
在package目录下有a1.py文件和subpackage1目录。在subpackage1目录下有b1.py文件。现在b1.py文件中有这样一行代码:from …a1 import A1。在subpackage1目录下运行python b1.py报错:ImportError: attempted relative import with no known parent package
问题复现
文件结构如下:
- package/
- init.py
- a1.py
- subpackage1/
- init.py
- b1.py
文件内容如下:
# -*- coding:utf-8 -*-
print(f"before import in {__file__}")
print(f"name: {__name__}")
print(f"package: {__package__}")
print(f"*"*120)
class A1:
def __init__(self) -> None:
print("A1")
if __name__ == "__main__":
demo = A1()
# -*- coding:utf-8 -*-
print(f"before import in {__file__}")
print(f"name: {__name__}")
print(f"package: {__package__}")
print(f"*"*120)
from ..a1 import A1
class B1:
def __init__(self) -> None:
print("B1")
if __name__ == "__main__":
print(__name__)
demo = B1()
这时候运行python b1.py会报错:ImportError: attempted relative import with no known parent package
解决方案
解决方式有两种:
- 以模块的方式运行
cd到package的上层目录,执行python -m pacakage.subpackage1.b1
这样,Python解释器就能正确解析相对导入,并导入A1
类了。
- 添加路径至sys.path中
在b1.py的文件开头添加以下内容:
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# 注意这里不是from ..a1
from a1 import A1
这段代码的作用是添加待导入文件a1.py所在的上级目录(即package目录)到sys.path里,这样Python解释器就能找到你的模块了。
这样就可以成功执行python b1.py了。
注意,这两种方式在导入A1类的时候有所区别
总结
在Python中,相对导入是基于包的结构进行的。为了使相对导入正常工作,需要让Python解释器找到待导入的文件所在的路径。一般可以通过以下两种方式达到:
- 以模块的方式运行的,而不是作为脚本直接运行的。即在package目录的上层目录(或更高层次的目录)中使用
python -m
xxx.xxx.b1命令来运行b1.py文件。 - 添加待导入文件(模块)所在的上级目录到sys.path。这样就可以通过python b1.by直接运行脚本文件。
https://stackoverflow.com/questions/14132789/relative-imports-for-the-billionth-time/14132912