【Python】python包相对导入问题及解决方案

报错信息

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

解决方案

解决方式有两种:

  1. 以模块的方式运行

cd到package的上层目录,执行python -m pacakage.subpackage1.b1

这样,Python解释器就能正确解析相对导入,并导入A1类了。

  1. 添加路径至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包相对导入问题及解决方案_第1张图片

总结

在Python中,相对导入是基于包的结构进行的。为了使相对导入正常工作,需要让Python解释器找到待导入的文件所在的路径。一般可以通过以下两种方式达到:

  1. 以模块的方式运行的,而不是作为脚本直接运行的。即在package目录的上层目录(或更高层次的目录)中使用python -m xxx.xxx.b1命令来运行b1.py文件。
  2. 添加待导入文件(模块)所在的上级目录到sys.path。这样就可以通过python b1.by直接运行脚本文件。

https://stackoverflow.com/questions/14132789/relative-imports-for-the-billionth-time/14132912

你可能感兴趣的:(Python,python)