关于Python如何避免循环导入问题详解


Posted in Python onSeptember 14, 2017

前言

Python 中使用package时,出现循环导入问题十分常见,我们创建如下package来说明这个问题:

pkg
 ├── __init__.py
 ├── module_a.py
 └── module_b.py

其中,

__init__.py 将pkg指定为一个Python package

module_a.py中定义了一个action_a()函数,该函数引用了module_b.py中的一个attribute,如一个函数或变量

module_b.py中定义了一个action_b()函数,该函数引用了module_a.py中的一个attribute,如一个函数或变量

这种情况下,执行该package时会抛出circular import error错误,即循环引用,因为module_a试图去引入module_b时,而module_b首先要引入module_a,这会导致Python解释器无法执行下去。

然而,我们可以通过一些巧妙的方法,让上面的逻辑正常工作,同时避免循环引入的错误。

那么,什么时候它能正常工作,什么时候不能正常工作,而那些能够正常工作的情况又是什么原因呢?

何时它能正常工作?

 1. 在module顶部引入,不要用from,相对引入,只在Python 2中有效

在module的顶部import,如import another_module,module 中的函数以another_module.attribute的方式引用another_module中的函数或变量等。这种方式之所以有效,是由于import another_module是基于当前目录的相对引用,而且是一种隐式引用,如果从另一个package中引入module时,就可以失效了。另外,import another_module这种语法在Python3 中已经不支持了,所以不要在代码中用这种方法来避免循环引入。

如:

# pkg/module_a.py 
from __future__ import print_function
import module_b
 
def action_a():
 print(module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
import module_a
 
def action_b():
 print(module_a.action_a.__name__)

2. 在module的顶部引入,不要用from,绝对引入

在module的顶部import,使用从package开始的绝对路径,如import package.another_module,module 中的函数以package.another_module.attribute的方式引用another_module中的函数或变量等。之所以要挂上package name来引入,是由于import .another_module这种形式的“相对引入”会报语法错误,而挂上package的绝对引入,Python 2和3都支持

案例:

# pkg/module_a.py
from __future__ import print_function
import pkg2.module_b
 
def action_a():
 print(pkg2.module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
import pkg2.module_a
 
def action_b():
 print(pkg2.module_a.action_a.__name__)

3. 在module底部引入another module的attribute,而非another module,用from

在module的底部import(至少要在被引用的attribute之后import),直接引入another module的attribute,如from package.another_module import attribute,相对引入也支持,如from .another_module import attribute,module中的函数直接使用被引用的attribute即可。

如:

# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 print(action_b.__name__)
 
from .module_b import action_b
 
 
# pkg/module_b.py
from __future__ import print_function
 
def action_b():
 print(action_a.__name__)
 
from .module_a import action_a

4. 函数顶部引入,可以用from

在module的function顶部import,如from package import another_module,也支持相对引入,引入module或attribute均可。

如:

# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 from . import module_b
 print(module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
 
def action_b():
 from . import module_a
 print(module_a.action_a.__name__)

# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 from .module_b import action_b
 print(action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
def action_b():
 from .module_a import action_a
 print(action_a.__name__)

这种方式虽然Python 2和3都支持,但编码不够优雅,影响代码可读性,不建议使用


本文讨论的问题,是Python中调用package时,应如何避免循环引入

当直接在命令行执行一个Python module时,适用情况不完全相同

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
wxpython 学习笔记 第一天
Mar 16 Python
python实现ftp客户端示例分享
Feb 17 Python
一些常用的Python爬虫技巧汇总
Sep 28 Python
使用Python对MySQL数据操作
Apr 06 Python
python模块之sys模块和序列化模块(实例讲解)
Sep 13 Python
Python实现的拟合二元一次函数功能示例【基于scipy模块】
May 15 Python
python粘包问题及socket套接字编程详解
Jun 29 Python
Python3.8对可迭代解包的改进及用法详解
Oct 15 Python
Python lxml模块的基本使用方法分析
Dec 21 Python
据Python爬虫不靠谱预测可知今年双十一销售额将超过6000亿元
Nov 11 Python
Python函数对象与闭包函数
Apr 13 Python
PYTHON InceptionV3模型的复现详解
May 06 Python
Python实现随机选择元素功能
Sep 14 #Python
python自动化脚本安装指定版本python环境详解
Sep 14 #Python
python实现八大排序算法(2)
Sep 14 #Python
Python3.4编程实现简单抓取爬虫功能示例
Sep 14 #Python
python实现八大排序算法(1)
Sep 14 #Python
python实现简单聊天应用 python群聊和点对点均实现
Sep 14 #Python
Python实现购物系统(示例讲解)
Sep 13 #Python
You might like
ThinkPHP快速入门实例教程之数据分页
2014/07/01 PHP
Laravel 5.3 学习笔记之 安装
2016/08/28 PHP
php 获取xml接口数据的处理方法
2018/05/31 PHP
laravel excel 上传文件保存到本地服务器功能
2019/11/14 PHP
javascript移动设备Web开发中对touch事件的封装实例
2014/06/05 Javascript
jQuery实现倒计时按钮功能代码分享
2014/09/03 Javascript
使用命令对象代替switch语句的写法示例
2015/02/28 Javascript
vue-router实现tab标签页(单页面)详解
2017/10/17 Javascript
浅谈mvvm-simple双向绑定简单实现
2018/04/18 Javascript
vue组件从开发到发布的实现步骤
2018/11/11 Javascript
javaScript实现一个队列的方法
2020/07/14 Javascript
jQuery使用hide()、toggle()函数实现相机品牌展示隐藏功能
2021/01/29 jQuery
[06:57]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD 选手采访
2021/03/11 DOTA
Python基于twisted实现简单的web服务器
2014/09/29 Python
用python实现面向对像的ASP程序实例
2014/11/10 Python
Python3读取UTF-8文件及统计文件行数的方法
2015/05/22 Python
构建Python包的五个简单准则简介
2015/06/15 Python
tensorflow 中对数组元素的操作方法
2018/07/27 Python
selenium3+python3环境搭建教程图解
2018/12/07 Python
详解Python进阶之切片的误区与高级用法
2018/12/24 Python
Python2.7实现多进程下开发多线程示例
2019/05/31 Python
python和mysql交互操作实例详解【基于pymysql库】
2019/06/04 Python
css3实例教程 一款纯css3实现的环形导航菜单
2014/10/20 HTML / CSS
socket.io 和canvas 实现的共享画板功能
2019/05/22 HTML / CSS
麦德龙官方海外旗舰店:德国麦德龙超市
2017/12/23 全球购物
加利福尼亚州威尼斯的女性奢侈品设计师服装和概念店:Mona Moore
2018/09/13 全球购物
LUISAVIAROMA德国官网:时尚奢侈品牌购物网站
2020/11/12 全球购物
Made in Design意大利:现代家具、名家灯具和装饰
2020/10/27 全球购物
师范生自荐信
2013/10/27 职场文书
大学生村官心得体会范文
2014/01/04 职场文书
退休党员个人对照检查材料思想汇报
2014/09/29 职场文书
医院领导班子查摆问题对照检查材料思想汇报
2014/10/08 职场文书
学校食品安全责任书
2015/01/29 职场文书
2015年园林绿化工作总结
2015/05/23 职场文书
2015年小学语文工作总结
2015/05/25 职场文书
CSS精灵图的原理与使用方法介绍
2022/03/17 HTML / CSS