python:import

python的引用有两种方式:绝对引用、相对引用,从形式上看,二者的区别就在于模块前面是否有...
后续解释均以下面结构为例:

xiaomeng
├─sub01
│   ├─a.py
│   ├─b.py
│
└─sub02
    └─sub01.py
  1. 绝对引用
    当使用绝对引用的方式时,python会从一系列既定的路径列表中依次搜索路径直到找到相应模块或者报错“模块xx不存在”。而这个路径列表就是sys.path
    当在a.py中使用print(sys.path)
['E:\\download_apps\\PyCharm 2022.1.3\\workplace\\xiaomeng\\root\\sub01', 'E:\\download_apps\\PyCharm 2022.1.3\\workplace\\xiaomeng', 
'E:\\download_apps\\PyCharm 2022.1.3\\plugins\\python\\helpers\\pycharm_display', 
'C:\\Users\\User_name\\.conda\\envs\\PY110\\python37.zip', ...]
这里的内容为:[运行文件所在目录,项目根路径,项目内置库目录,...,手动append目录]
  • a import b
    nfsq
    运行a.py文件时,python就会从a的sys.path中依次寻找包含了b的路径,如果找不到就提示“b模块不存在”
    nfsq

  • a import demo01
    当使用a引用demo01时,
    nfsq
    由于a的sys.path不包含root路径,所以就会找不到demo01模块:
    nfsq
    当然我们可以从项目根路径出发,通过import root.sub01.demo0来访问到,但是现在我就想从root出发通过import sub01.demo01来访问demo01。所采取的方法应该是讲这个root路径添加到sys.path中,
    具体为
    nfsq
    结果正确:
    nfsq

  1. 相对引用
    当使用绝对引用的方式时,python会以主引用文件的__name__为起点查找被引用文件。
    这里会有两种错误:ImportError: attempted relative import with no known parent packageValueError: attempted relative import beyond top-level package
  • 入口文件相对引入
    对于入口文件(初始运行的文件)而言,它的__name__一定是__main__,所以,如果入口文件使用相对引入,那么查找路径就相当于__main__.xx,而项目中本就没有__main__这个文件存在,所以就会报错“非法父目录”,即ImportError: attempted relative import with no known parent package
    所以,入口文件不要使用相对引用方式。
    nfsq

  • 非入口文件相对引入
    对于非入口文件,它的__name__取决于被引用的方式:
    nfsq
    这里a的__name__就是在demo01中引用的那样,而此时在a中的相对引入就从root/sub01出发,自然能找得到b

  1. 报错:ValueError: attempted relative import beyond top-level package
    在第二小节中已经提到过这个错误。顾名思义,这个错误发生在相对引入的路径超出了最高级路径导致的,只要明白这个“top-level”,一切都好解决了。
    实际上,这个“top-level”指的是__name__的"top-level",如:
    nfsq
    这里a的__name__为sub01.a,以sub01为起点开始查找,而from ..b对应的路径则是sub01..b,这里sub01已经是__name__中的"top-level",再向上查找一级就会报错“超出top-level”。
posted @ 2022-10-23 20:16  YIYUYI  阅读(116)  评论(0编辑  收藏  举报