python3导入模块原理_Python模块导入机制与规范

前言

在我们平常工程里使用Python的过程中,经常需要解决各个模块的导入问题,而且也常常遇到引用路径查找不到、交叉导入模块等等问题,故写这篇文章,旨在讲述Python的模块导入机制和我们平时大型项目中应该遵循的模块导入规范

Python模块导入

日常编程中,为了能够复用写过的代码逻辑,我们都会把这些代码封装成为模块,需要用到的时候可以直接导入复用,以便提高我们的开发效率。 module能定义函数、类、变量,也能包含可执行的代码。module来源有3种: ①Python内置的模块(标准库); ②第三方模块; ③自定义模块;

导入原理

模块的导入一般是在文件头使用import关键字,import一个模块相当于先执行了一次这个被导入模块,然后在本命名空间建立一个与被导入模块命名空间的联系,相当于在本命名空间新建了一个变量,这个变量名称是被导入模块的名称,指向被导入模块的命名空间。所以导入的这个模块相当于一个变量,因此多次导入同一个模块只有第一次导入的时候会被执行(后续导入会判断到这个模块变量已存在所以不执行)

路径查找机制

每一个导入的模块都会在Python内置字典sys.modules中,Python一启动,它将被加载在内存中,当我们导入新modules,sys.modules将自动记录下该module。 Python的模块查找路径的机制是: 1. 查找sys.path中的所有路径下是否有该模块,有则开辟新空间加载该模块; 2. 查看sys.modules中是否有内置包或已安装的第三方包,有则开辟新空间加载该模块;

所以对于我们自己编写的模块,如果封装并发布到了PyPi,则可以用pip install直接安装,并在启动时加载在内存中,通过sys.modules可以查看到 而对于仅需要在本项目中复用的模块,我们在复用代码中将其路径加入到sys.path中,同样可以引用到该模块。

绝对路径导入

所有的模块import都从“根节点”开始。根节点的位置由sys.path中的路径决定,项目的根目录一般自动在sys.path中。如果希望程序能处处执行,需手动修改sys.path

import sys,os

BASE_DIR = os.path.dirname(os.path.abspath(__file__))#项目根目录所在的绝对路径

sys.path.append(BASE_DIR)

import A, B #导入A、B包

相对路径导入

只关心相对自己当前目录的模块位置就好。不能在包(package)的内部直接执行(会报错)。不管根节点在哪儿,包内的模块相对位置都是正确的。

#from . import b2 #这种导入方式会报错,只有在包内部直接执行的时候才可以这样导入。

import b2#正确

b2.print_b2()

Python模块导入常见问题单独import某个包名称时,不会导入该包中所包含的所有子模块 解决办法:导入的包中也包含了其他包的导入,此时需要在每个包的init.py文件中导入该包下的所有模块,最上层才可以直接引用最下层的包的类和方法

init文件

当一个文件夹下有init.py时,意为该文件夹是一个包(package),其下的多个模块(module)构成一个整体,而这些模块(module)都可通过同一个包(package)导入其他代码中。 其中init.py文件 用于组织包(package),方便管理各个模块之间的引用、控制着包的导入行为。

该文件可以什么内容都不写,即为空文件(为空时,仅仅用import [该包]形式 是什么也做不了的),存在即可,相当于一个标记。

在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包会报错

all变量

all 是一个重要的变量,用来指定此包(package)被import *时,哪些模块(module)会被import进【当前作用域中】。不在all列表中的模块不会被其他程序引用。可以重写all,如 all= [‘当前所属包模块1名字’, ‘模块1名字’],如果写了这个,则会按列表中的模块名进行导入

name变量

在包内部直接运行时,包的name == 'main',但是在外部导入包是,可以通过

if __name__ == '__main__':

来避免实现包内部调试时的逻辑

循环导入

当两个模块A和B之间相互import时,就会出现循环导入的问题,此时程序运行会报错:can not import name xxx,如:

# a.py

print('from a.py')

from b import x

y = 'a'

# b.py

print('from b.py')

from a import y

x = 'b'

我们来分析一下这种错误是怎么出现的: 1. 在sys.modules中查找 符号“module b”; 2. 如果符号“module b”存在,则获得符号“module b”对应的module对象; 从的dict中获得 符号“x”对应的对象。如果“x”不存在,则抛出异常“ImportError: cannot import name ‘x’” 3. 如果符号“module b”不存在,则创建一个新的 module对象。不过此时该新module对象的dict为空。然后执行module b.py文件中的语句,填充的dict。

因此在a.py中执行from b import x的顺序就是1->3,先引入b,b里面from a import y由相当于执行了a.py,顺序是1->2,因为此时b已经引入所以不会执行3,2中无法找到x对象,因为引入b时还没执行到x='b'这一步,所以报错了

解决办法延迟导入,把import语句写在方法/函数里,将它的作用域限制在局部;

顶层先引入模块,再把from x import y改成import x.y形式;

其实出现循环引用问题的根本原因是程序设计不合理,每个包都应该由上层使用的模块去导入,而不应该在包与包之间各种相互导入,所以应该更改代码布局,可合并或分离竞争资源;

大型项目中Python模块导入规范分离模块,将同一类别的模块放在同一目录下,形成类别分明的目录架构,如:

每一个模块目录都要写init.py文件,可以同时定义all限定可导入的范围;

源码根目录可以定义BASE_DIR,限定好根目录路径,启动py文件可以用绝对路径导入各个模块,将必要模块都加入到sys.path中;

各个服务之间(例如model需要引入common的模块方法),可以通过相对路径引用模块;

程序设计时避免循环导入,可由调用者(服务文件)作为上层第三方引入需要的各个模块,这样就可以减少各个模块的相互导入。

参考文献

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

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

相关文章

canfd收不到数据_在AWR1642评估板上测试CAN-FD,能发送数据,不能接收数据

在AWR1642评估板上运行mmwave_automotive_toolbox_2_7_1\labs\lab0005_object_data_over_can例程,使用周立功的USB2CAN转换器和上位机软件,基于此例程测试CAN-FD发送和接收数据,能向上位机软件发送数据,但不能接收到上位机软件发送…

Shell脚本完成hadoop的集群安装

虽然整体实现的自动安装,但还是有很多需要完善的地方,比如说: 1. 代码目前只能在root权限下运行,否则会出错,这方面需要加权限判断; 2.另外可以增加几个函数,减少代码冗余; 3.还有一…

usb接口多少钱_工控机一般有多少个串口

工控机跟普通电脑特别明显的区别在于工控机的主板有各种丰富的槽位,可以插各种运动控制卡。比如工控机串口、USB口、网口和独立显卡等等。所以,有很多客户在沟通中,都会问我们你这款工控机一般有多少个串口?多少个USB口等等之类的…

python和c先学哪一个_python和c先学哪个

编程是一门手艺。学习编程,首先必须有一个目的。事实上,你可以学习任何语言,因为语言是可互操作的,C语言是好的,和Python也非常适合初学者。让我们仔细看看!对于那些不主修计算机科学,python和c是第一个学习。学习编程最重要的事情就是保持兴趣,不要缠绕技能树的问题。至于学习…

python的模块导入问题_python导入模块错误怎么解决

经常在运行一些Python项目的时候会出现模板报错的情况,比如以下的报错信息:Traceback (most recent call last): File "D:/Python/Demo/mapdemo/chinamap.py", line 1, in import matplotlibs.pyplot as plt ImportError: No module named ma…

大学生计算机python_非计算机专业的大学生,想学习Python需要多长时间

非计算机专业的学生,在学习Python的时候,有一个难关——那就是知识的应用。而知识的应用,反应的就是编程的能力。度过这个难关需要多久呢?我觉得,这和每个人的学习能力、学习方法都有关系。非计算机专业的大学生,想学习…

IOS开发之分享

在我们IOS软件开发当中我们有事需要分享一些图片视屏和文档之类的东西。但是有可能用的是别的软件,这时候我们就需要学习分享。 我们举个分享微信的例子好了: 看代码 先看AppDelegate.m文件内容 在AppDelegate.m里面我们需要 [WXApi registerApp:"w…

cmake install_在vscode中使用cmake-format(windows端)

cmake作为一个跨平台的构建工具,在开源社区得到了广泛运用,并且在项目中被大量采用,但是cmake作为一个类脚本的语言,基本上没有编辑器很好的支持代码自动补全和提示,所有在我们往往需要边查cmake文档边写cmake模块&…

currentTitle的用法

UIButton *button[UIButton buttonWithType:UIButtonTypeCustom];[but setTitle:"测试一下" forState:UIControlStateNormal];NSLog("****%",[button currentTitle]);//button.currentTitleNSLog("******%",button.titleLabel.text);两者输出的结…

python返回函数值并退出函数_如何在python的阻塞的函数中获取变量值

目前是使用C嵌入式的python函数 python函数是阻塞式的接收服务器消息 直到退出监听才会有返回值 监听中收到消息会调用python的一个回调函数,可以获取到收到的消息 所以要怎么样来返回消息给C EDIT: 代码如下callback打印可以打印正确数据,问题是 这里用…

gb50243-2016通风与空调工程施工质量验收规范_07K304 空调机房设计与安装

免费下载07K304 空调机房设计与安装百度网盘网址:链接:https://pan.baidu.com/s/1gKEyKH-6MrwbBcV87E2o8g提取码: tzpf空调机房设计与安装批准部门:中华人民共和国建设部 批准文号∶建质【2007】180号主编单位:中国电…

mooc_java 集合框架中 学生所选课程2MapHashMap

Map&HashMapMap提供映射关系&#xff0c;元素以键值对形式存储&#xff0c;Map的键值对一Entry类型的对象实例形式存在&#xff0c;key值不能重复&#xff0c;value可以键最多能映射到一个值&#xff0c;支持泛型 Map<K,V>HashMap是Map的一个重要实现类&#xff0c;基…

python爬虫反爬对抗_python爬虫反反爬,你几乎可以横扫大部分 css 字体加密的网站...

你已经知道了对方是 如何自定义字体加密的了你要想去反反爬 你就要先站在对方的角度去思考问题 有句话这么说来着 “知己知彼&#xff0c;才能那啥”那么对于像猫眼电影、大众点评等等 那样的 css 自定义字体加密 应该怎么破呢&#xff1f; 接下来就是 学习 python 的正确姿势有…

依赖注入底层反射原理_PHP反射机制实现自动依赖注入

依赖注入又叫控制反转&#xff0c;使用过框架的人应该都不陌生。很多人一看名字就觉得是非常高大上的东西&#xff0c;就对它望而却步&#xff0c;今天解开他它的神秘面纱。废话不多说&#xff0c;直接上代码&#xff1b;/**** 工具类&#xff0c;使用该类来实现自动依赖注入。…

“Transaction rolled back because it has been marked as rollback-only”

spring的声明事务提供了强大功能&#xff0c;让我们把业务关注和非业务关注的东西又分离开了。好东西的使用&#xff0c;总是需要有代价的。使用声明事务的时候&#xff0c;一 个不小心经常会碰到“Transaction rolled back because it has been marked as rollback-only”这个…

c++获取时间戳_时间简史

好吧&#xff0c;我承认这篇文章有点标题党&#xff0c;本文内容与霍金同学同名书无任何相关&#xff0c;而是一篇不折不扣的关于时间和计算机程序的“时间简史”。时间是什么&#xff1f;数学家说时间是第四维度&#xff0c;不过显然计算机不这么看&#xff0c; 在计算机的世界…

cmake添加查找目录_CMakeLists.txt文件写法(7):添加查找头文件的路径

[1.List转换成为数组。(这里的List是实体是ArrayList)   调用ArrayList的toArray方法。  toArray  public T[] toArray(T[] a)返回一个按照正确的顺序包含此列表中INCLUDE_DIRECTORIES: Add include directories to the build.[ 最近在学习Linux下的C编程&…

[iOS] 建立与使用Framework

[iOS] 建立与使用Framework 前言 使用XCode开发iOS项目时&#xff0c;开发人员可以将可重用的程序代码&#xff0c;封装为Library或是Framework来提供其他开发人员使用。这两种封装方式在使用的时候&#xff1a;Library需要将.a封装档与所有公开的.h档提供给使用者加入项目&…

a标签点击事件_html常用标签

一、a标签作用&#xff1a;1、跳转到外部页面&#xff1b;2、跳转到内部锚点&#xff1b;3、跳转到邮箱或电话。属性&#xff1a;href&#xff08;hyperreference&#xff09;&#xff1a;超级引用、超级链接1、a的href的取值&#xff1a;<//http://google.com&#xff1a;无…

mysql导出表_mysql导出表的3种方式

文章转载自 &#xff1a;https://blog.csdn.net/jbb0403/article/details/26359573navicat导出表一共有三中用法&#xff1a;第一种&#xff1a;数据库上右键—>"转储SQL文件"&#xff0c;如图&#xff1a;"转储文件"是把整个数据库表全部导出&#xff…