在python内置集成开发环境中,python模块导入的几种方法

  在python内置集成开发环境中,python模块导入的几种方法

  今天Python视频教程专栏介绍你学习Python模块的导入机制和大型项目的规范。

  00-1010-

在我们平时的项目中使用Python的过程中,经常需要解决各个模块的导入问题,经常会遇到引用路径找不到、模块交叉导入等问题。因此,写这篇文章是为了讲述Python的模块导入机制,以及我们在通常的大型项目中应该遵循的模块导入规范。

  00-1010在日常编程中,为了复用编写的代码逻辑,我们会把这些代码打包成模块,需要的时候可以直接导入复用,提高我们的开发效率。

  该模块可以定义函数、类和变量,也可以包含可执行代码。有三种类型的模块:

  Python的内置模块(标准库);

  第三方模块;

  自定义模块;

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

  00-1010每个导入的模块都将在Python的内置字典sys.modules.中。一旦Python启动,它将被加载到内存中。当我们导入新模块时,sys.modules会自动记录该模块。

  Python的模块搜索路径机制是:

  找出该模块是否存在于sys.path,中的所有路径下,如果存在,则打开一个新的空间来加载该模块;检查sys.modules中是否有内置包或已安装的第三方包,如果有,则开辟新的空间加载该模块;所以对于自己写的模块,如果打包发布到PyPi,可以直接用pip install安装,启动时加载到内存中,可以通过sys.modules查看

  对于本项目中只需要复用的模块,我们在复用代码中将其路径添加到sys.path,也可以引用该模块。

  00-1010所有模块从“根节点”导入。根节点的位置由sys.path中的路径决定,项目的根目录一般自动在sys.path中,如果想让程序到处执行,需要手动修改sys.path

  导入系统、操作系统

  base _ dir=OS . path . dirname(OS . path . ABS path(_ _ file _ _)#项目根目录所在的绝对路径sys.path.append (base _ dir)。导入A,B #导入包A和B复制代码

前言

。只需要关心模块相对于当前目录的位置。它不能在包内直接执行(将会报告一个错误)。无论根节点在哪里,包中模块的相对位置都是正确的。

  #来自。import b2 #这个导入方法会报错,只有在包内直接执行才能导入。B2 # Correct b2.print_b2()当复制代码

Python模块导入

单独导入一个包名时,包中包含的所有子模块都不会被导入。

  解决方案:导入的包还包括其他包的导入。此时需要将每个包下的所有模块导入到每个包的init.py文件中,这样最底层的包的类和方法就可以被顶层直接引用。

导入原理

当一个文件夹中有init.py时,说明这个文件夹是一个包,它下面的几个模块形成一个整体,所有这些模块都可以通过同一个包导入到其他代码中。其中,init. py文件用于组织包,方便管理模块间的引用,控制包的导入行为。

  文件可以什么都不写,就是一个空文件(空的时候仅仅用导入[包]的形式什么都做不了),可以存在,相当于一个标记。

  在python3中,即使包下没有在python3中,即使包下没有init. py文件,导入包也不会报错,而在python2中,文件必须在包下,否则导入包会报错。

  

路径查找机制

  strong>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.pyprint('from a.py')from b import x

  y = 'a'复制代码

# b.pyprint('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'这一步,所以报错了

  

解决办法

  1. 延迟导入,把import语句写在方法/函数里,将它的作用域限制在局部;
  2. 顶层先引入模块,再把from x import y改成import x.y形式;
  3. 其实出现循环引用问题的根本原因是程序设计不合理,每个包都应该由上层使用的模块去导入,而不应该在包与包之间各种相互导入,所以应该更改代码布局,可合并或分离竞争资源;

大型项目中Python模块导入规范

分离模块,将同一类别的模块放在同一目录下,形成类别分明的目录架构,如:

  

  1. 每一个模块目录都要写init.py文件,可以同时定义all限定可导入的范围;
  2. 源码根目录可以定义BASE_DIR,限定好根目录路径,启动py文件可以用绝对路径导入各个模块,将必要模块都加入到sys.path中;
  3. 各个服务之间(例如model需要引入common的模块方法),可以通过相对路径引用模块;
  4. 程序设计时避免循环导入,可由调用者(服务文件)作为上层第三方引入需要的各个模块,这样就可以减少各个模块的相互导入。
更多相关免费学习推荐:python视频教程

  

以上就是学习Python模块导入机制与大型项目的规范的详细内容,更多请关注盛行IT软件开发工作室其它相关文章!

  

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: