python中遇到循环import即circular import的问题原理剖析及解决方案

在python中常常会遇到循环import即circular import的问题,今天主要给大家介绍了关于Python中循环引用(import)失败的解决方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴。

一、前言

最近在开发智能家居项目项目中,由于代码结构层级划分不合理,导致了循环引用(import)module失败的问题,错误如下:

  File "./design_app/views.py", line 7, in <module>
    import alg.auto_design.evaluate as evaluate
  File "./alg/auto_design/evaluate.py", line 5, in <module>
    from alg.auto_design.helpers.json_io import json2fp
  File "./alg/auto_design/helpers/__init__.py", line 2, in <module>
    from alg.auto_design.helpers import json_io
  File "./alg/auto_design/helpers/json_io.py", line 14, in <module>
    from alg.auto_design.room_type.dingroom.base import DiningRoom
  File "./alg/auto_design/room_type/dingroom/base.py", line 13, in <module>
    from alg.auto_design_easyhome.utility import get_opposite_bounds
  File "./alg/auto_design_easyhome/utility.py", line 8, in <module>
    from alg.auto_design_easyhome.room_type.master_bedroom import \
  File "./alg/auto_design_easyhome/room_type/master_bedroom/__init__.py", line 3, in <module>
    from alg.auto_design_easyhome.room_type.master_bedroom.base import MainBedroom
  File "./alg/auto_design_easyhome/room_type/master_bedroom/base.py", line 6, in <module>
    from alg.auto_design_easyhome.helpers import extract_rec
  File "./alg/auto_design_easyhome/helpers/__init__.py", line 2, in <module>
    from alg.auto_design_easyhome.helpers import json_io
  File "./alg/auto_design_easyhome/helpers/json_io.py", line 14, in <module>
    from alg.auto_design_easyhome.room_type.dingroom.base import DiningRoom
  File "./alg/auto_design_easyhome/room_type/dingroom/base.py", line 13, in <module>
    from alg.auto_design_easyhome.utility import get_opposite_bounds
ImportError: cannot import name 'get_opposite_bounds' from partially initialized module 'alg.auto_design_easyhome.utility' (most likely due to a circular import) (./alg/auto_design_easyhome/utility.py)

二、import执行过程

当我们import一个文件时,python会首先去查找这个文件之前是否被import过,如果这个文件之前有被import过,就不会重新再import一次。所以如果A模块
代码里import了B模块,并且B模块里又import了A模块,python的执行顺序会变成这样:

  • 开始执行模块A
  • 当A执行到import B的地方,则停止执行A模块后面的代码,转而开始执行B模块的代码
  • 当B模块从头执行到import A的地方时,python此时并不会回过头去接着执行A剩余的代码,而且将A模块在中断前已经初始化的属性全加载到B模块中

三、原理

这个时候就有一个问题,当前脚本Main第一次执行,需要执行from A import ,发现没有A,就新建一个A在内存中,然后填充A模块的信息,就会去执行A,此时,A里面要 from Main import D,那么因为Main已被执行,就直接从内存的map中取得Main的信息,不过此时Main的信息还没有填充完,因为之前就是为了填充才转到A的,这时从已有的空的Main中拿不到D,就会报错,ImportError。

四、解决方案

1、方案一 合理划分项目代码层级

循环引用最大的本质问题是代码层级结构划分的不合理,所以最根本的、最合理的解决方案就是重新划分好代码的层级结构,使其合理化,自然就规避了循环引用的麻烦。

2、方案二 只引用当前的包,不引用具体的模块

如果你的代码是这样,那么这种方式是会奏效的。

案例一:修改前

# a.pyfrom B import bdef a():pass# some codes# b.pyfrom A import adef b():a.a()#some codes

案例一:修改后

# a.pyfrom B import bdef a():pass# some codes# b.pyimport Adef b():A.a.a()#some codes

2、方案二 将引用放到函数内部

如果你的代码是这样,那么这种方式是会奏效的。

案例二:修改前

# a.pyfrom B import bdef a():pass# some codes# b.pyfrom A import adef b():a.a()#some codes

案例二:修改后

# a.pyfrom B import bdef a():pass# some codes# b.pydef b():from A import aa.a()#some codes

五、总结

只有理解了python在import时的工作原理,这种cicular import的问题才会很好的分析和解决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473224.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1711. 大餐计数(map计数 + 二分查找)

文章目录1. 题目2. 解题1. 题目 大餐 是指 恰好包含两道不同餐品 的一餐&#xff0c;其美味程度之和等于 2 的幂。 你可以搭配 任意 两道餐品做一顿大餐。 给你一个整数数组 deliciousness &#xff0c;其中 deliciousness[i] 是第 i​​​​​​​​​​​​​​ 道餐品的美…

node.js初入手

今天突然看到《node.js开发指南》的pdf文件&#xff0c;感觉封面不错&#xff0c;就看看。发现写的挺好的。 一、mac下安装 http://nodejs.org/download/ //官网下载mac版 二、用npm安装supervisor (检测修改&#xff0c;则重启node进程) sudo npm install -g supervisor //…

总结与整理:Ubuntu系统下安装、配置Nginx及其他注意事项

在Ubuntu下安装Nginx有以下方法&#xff0c;但是如果想要安装最新版本的就必须下载源码包编译安装。 一、基于APT源安装 sudo apt-get install nginx 1、安装好的文件位置&#xff1a; /usr/sbin/nginx&#xff1a;主程序 /etc/nginx&#xff1a;存放配置文件 /usr/share/n…

LeetCode 1710. 卡车上的最大单元数(排序,模拟)

文章目录1. 题目2. 解题1. 题目 请你将一些箱子装在 一辆卡车 上。给你一个二维数组 boxTypes &#xff0c;其中 boxTypes[i] [numberOfBoxesi, numberOfUnitsPerBoxi] &#xff1a; numberOfBoxesi 是类型 i 的箱子的数量。numberOfUnitsPerBoxi 是类型 i 每个箱子可以装载…

hdu 1505 City Game

http://acm.hdu.edu.cn/showproblem.php?pid1505 先处理每一行上每一个F为底往上所到达的高度&#xff0c;然后再左右处理。 1 #include <cstdio>2 #include <cstring>3 #include <algorithm>4 #define maxn 10015 using namespace std;6 7 int t;8 int n,m…

使用Python requests post上传图片及示例demo

一、需求&#xff1a; 利用python写demo&#xff0c;上传图片&#xff0c;调用接口&#xff0c;并返回数据 二、requests上传图片参数&#xff1a; resrequests.request("POST",url, dataNone, filesfiles) 三、demo示例&#xff1a; import json import osimpo…

LeetCode 1712. 将数组分成三个子数组的方案数(前缀和 + 二分查找)

文章目录1. 题目2. 解题221 / 3117&#xff0c;前7.1%574 / 9692&#xff0c;前 5.9%周赛前2题如下&#xff1a; LeetCode 5641. 卡车上的最大单元数&#xff08;排序&#xff0c;模拟&#xff09; LeetCode 5642. 大餐计数&#xff08;map计数 二分查找&#xff09; 第4题&am…

总结python处理图片等比例压缩与质量处理的方法

一、使用PIL image 处理 1、在使用PIL image处理图像要获取高质量的关键地方是下面两点&#xff1a; 1、处理时要用 ANTIALIAS&#xff1b;2、保存时是要设置 quality&#xff1b; 2、在python ide 可以这样处理&#xff1a; im.resize(box, Image.ANTIALIAS) im.save(path…

第六周交流会内容

第六周 交流会 -bO莱特 一、接口作为参数&#xff0c;不同的接口调用不同的方法&#xff0c;例如&#xff1a;输出“I love Game”或输出“我喜欢游戏” 接口的思想&#xff1a;在于可以增加很多类都需要实现的功能。比如&#xff1a;各式各样的商品&#xff0c;可能隶属不同公…

Python基础代码练习(30个示例)

1、冒泡排序 2、计算x的n次方的方法 3、计算a*a b*b c*c …… 4、计算阶乘 n! 5、列出当前目录下的所有文件和目录名 6、把一个list中所有的字符串变成小写&#xff1a; 7、输出某个路径下的所有文件和文件夹的路径 8、输出某个路径及其子目录下的所有文件路径 9、输出某个路…

LeetCode 1713. 得到子序列的最少操作次数(最长上升子序DP nlogn)

文章目录1. 题目2. 解题1. 题目 给你一个数组 target &#xff0c;包含若干 互不相同 的整数&#xff0c;以及另一个整数数组 arr &#xff0c;arr 可能 包含重复元素。 每一次操作中&#xff0c;你可以在 arr 的任意位置插入任一整数。 比方说&#xff0c;如果 arr [1,4,1,…

ubuntu 16.04系统中nvidai、cuda、cudnn安装及注意事项

一、NVIDAI driver显卡驱动安装 首先看一下笔记本显卡型号 lspci |grep VGA 在命令行敲过这个命令后&#xff0c;有些台式机或笔记本会显示nvidia显卡&#xff0c;如下所示&#xff1a; 但是我的笔记本电脑 只显示nouveau卡&#xff08;集成显卡&#xff09; 需要执行下面命…

LeetCode 552. 学生出勤记录 II(动态规划)

文章目录1. 题目2. 解题1. 题目 给定一个正整数 n&#xff0c;返回长度为 n 的所有可被视为可奖励的出勤记录的数量。 答案可能非常大&#xff0c;你只需返回结果mod 10^9 7的值。 学生出勤记录是只包含以下三个字符的字符串&#xff1a; A : Absent&#xff0c;缺勤 L : L…

ubuntu定时执行python脚本方法及实例代码

一、前言 本文将介绍ubuntu系统下如何定时执行shell脚本、python脚本&#xff0c;ubuntu系统有一个定时任务的管理器crontab&#xff0c;我们只需要编辑定时任务&#xff0c;然后重启定时任务服务就好了。 二、工具&#xff1a;crontab a、编辑定时任务&#xff1a; crontab -…

LeetCode 940. 不同的子序列 II(动态规划)

文章目录1. 题目2. 解题1. 题目 给定一个字符串 S&#xff0c;计算 S 的不同非空子序列的个数。 因为结果可能很大&#xff0c;所以返回答案模 10^9 7. 示例 1&#xff1a; 输入&#xff1a;"abc" 输出&#xff1a;7 解释&#xff1a;7 个不同的子序列分别是 &qu…

[Jmeter]Jmeter环境搭建

Jmeter环境搭建 1、 拷贝 \\szpc1450\apache-jmeter-2.7 整个目录到本机(我是放在D盘&#xff0c;以下路径说明以D盘为例) 2、 拷贝\\szpc1450\Tools\autotest softwares\jdk-6u11-windows-i586-p.exe到本机之后进行安装 安装完毕之后添加环境变量 JAVA_HOME C:\Program File…

Python获取磁盘使用信息,python获取GPU信息,python根据进程号获取进程信息,pynvml 获取GPU信息,psutil 获取进程信息,系统信息等

一、工具&#xff1a;psutil模块 psutil是一个跨平台模块&#xff0c;试用相应方法可以直接获取计算机CPU&#xff0c;内存&#xff0c;磁盘&#xff0c;网络等资源使用情况&#xff1b;可以使用我们学习知识与这模块用来做系统监控&#xff0c;性能分析&#xff1b;如果大家熟…

LeetCode 907. 子数组的最小值之和(单调栈)

文章目录1. 题目2. 解题1. 题目 给定一个整数数组 A&#xff0c;找到 min(B) 的总和&#xff0c;其中 B 的范围为 A 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff0c;因此返回答案模 10^9 7。 示例&#xff1a; 输入&#xff1a;[3,1,2,4] 输出&a…

Python环境下,提高pip安装库速度的方法!

一、前言 学习 Python 的话&#xff0c;仅掌握标准库是远不够的&#xff0c;有很多好用的第三方库我们也需要用到的 大家发现 pip install 包名 的方式 安装第三方库的时候&#xff0c;下载速度很慢&#xff0c;有时还会超时&#xff0c;遇到第三方库比较大时候&#xff0c;…

静态变量与静态方法

1&#xff0e;静态变量在C#程序中&#xff0c;没有全局变量的概念&#xff0c;这意味着所有的成员变量只有该类的实例才能操作这些数据&#xff0c;这起到了“信息隐藏”的作用。但有些时候&#xff0c;这样做却不是个明智的选择。假设我们要定义一个图书类&#xff0c;要求该类…