python实现同级目录调用的示例详解

前言

通过制作简易的Demo,让其更加深入的了解如何使用

6a4e8fc2ee8880a1bebfacccb9bb5cad

1. 问题所示

发现python的同级目录相互调用会出Bug

E:\\software\\anaconda3\\envs\\py3.10\\python.exe F:\\python_project\\test\\Father\\child\\file3.py 
Traceback (most recent call last):
  File \"F:\\python_project\\test\\Father\\child\\file3.py\", line 1, in <module>
    from ..file1 import greet  # 这将失败,没有 __init__.py
ImportError: attempted relative import with no known parent package

Process finished with exit code 1

截图如下:

fb69b076d5d8ae58049f14facd772161

2. 原理分析

出现 ImportError: attempted relative import with no known parent package 错误的原因是 Python 无法识别当前脚本的父包,因此相对导入失败

要解决这个问题并理解其背后的原理,需要了解以下几点:

原理分析

相对导入的限制

相对导入(例如,from …module import something)只能在包(包含 __init__.py 文件的目录)中使用
当运行脚本时,如果它所在的包没有正确识别,Python无法解析相对导入

脚本直接运行的问题

如果直接运行一个脚本(例如,通过 python file3.py),该脚本的包上下文不会被识别
相对导入会失败,因为Python不知道如何定位脚本的父包

3. 解决方法

先给一个Demo

其文件结构如下:

test/
├── Father/
│   ├── file1.py
│   └── child/
│       └── file3.py

file1如下:

def greet():
    print(\"Hello from file1\")

file3如下:

from ..file1 import greet  # 这将失败,没有 __init__.py

def main():
    greet()

if __name__ == \"__main__\":
    main()

这将执行出错

通用的解决方式有如下:

3.1 添加父目录

在file3中修改代码为如下:

import sys
import os

# 将父目录添加到 sys.path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from Father.file1 import greet

def main():
    greet()

if __name__ == \"__main__\":
    main()

执行的结果如下:

4dd403af968b98fa300072f3d4e74a94

3.2 相对路径

修改file3如下:

from ..file1 import greet

def main():
    greet()

if __name__ == \"__main__\":
    main()

但是 执行结果如下:

6e1829fbe439f593bd51fe3485c0430e

需要使用命令行的方式来执行:

e80440dfae0a4fb0548220772691cbc0

注意差异

如果file3的文件如下:

from Father.file1 import greet

def main():
    greet()

if __name__ == \"__main__\":
    main()

还是可以直接运行的:

77407d4e3871848796e5a9322386ccdd

3.3 添加init

截图如下:

6338bd37049d6c5c98c00ec3d611b6ce

对应file3的文件如下:

from Father.file1 import greet

def main():
    greet()

if __name__ == \"__main__\":
    main()

截图如下:

1388c31534f92d92a40d683806bddd3a

也可使用命令行的方式来执行:

e80440dfae0a4fb0548220772691cbc0

__init__.py 文件在 Python 3.3 及其之后的版本中不是必须的,但它有助于将目录标识为一个包

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容