Python 3.x | 史上最详解的 导入(import)(python123平台登录)

admin 2766 2022-09-08

本文转载自网络公开信息

Python 3.x | 史上最详解的 导入(import)(python123平台登录)

win10+Python 3.6.3

Python 3.x | 史上最详解的 导入(import)(python123平台登录)

一旦使用多层文件架构就很容易遇上import的坑!哈哈。

一、理解一些基本概念

1、模块、包

**模块 module:**一般情况下,是一个以.py为后缀的文件。其他可作为module的文件类型还有".pyo"、".pyc"、".pyd"、".so"、".dll",但Python初学者几乎用不到。

module 可看作一个工具类,可共用或者隐藏代码细节,将相关代码放置在一个module以便让代码更好用、易懂,让coder重点放在高层逻辑上。

module能定义函数、类、变量,也能包含可执行的代码。module来源有3种:

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

②第三方模块;

③自定义模块。

其中   init   .py文件 用于组织包(package),方便管理各个模块之间的引用、控制着包的导入行为。

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

但若想使用from pacakge_1 import *这种形式的写法,需在  init  .py中加上:   all    = [‘file_a’, ‘file_b’] #package_1下有file_a.py和file_b.py,在导入时   init   .py文件将被执行。

但不建议在   init   .py中写模块,以保证该文件简单。不过可在   init   .py导入我们需要的模块,以便避免一个个导入、方便使用。

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

在模糊导入时,形如from package import *,*是由__all__定义的。

精确导入,形如 from package import *、import package.class。

path   也是一个常用变量,是个列表,默认情况下只有一个元素,即当前包(package)的路径。修改   path   可改变包(package)内的搜索路径。

当我们在导入一个包(package)时(会先加载   init   .py定义的引入模块,然后再运行其他代码),实际上是导入的它的   init   .py文件(导入时,该文件自动运行,助我们一下导入该包中的多个模块)。我们可以在   init   .py中再导入其他的包(package)或模块 或自定义类。

2、sys.modules、命名空间、模块内置属性

2.1 sys.modules

官方解释:链接

sys.modules 是一个 将模块名称(module_name)映射到已加载的模块(modules) 的字典。可用来强制重新加载modules。Python一启动,它将被加载在内存中。

当我们导入新modules,sys.modules将自动记录下该module;当第二次再导入该module时,Python将直接到字典中查找,加快运行速度。

它是个字典,故拥有字典的一切方法,如sys.modules.keys()、sys.modules.values()、sys.modules[‘os’]。但请不要轻易替换字典、或从字典中删除某元素,将可能导致Python运行失败。

import sys

2.2 命名空间如同一个dict,key 是变量名字,value 是变量的值。

每个函数function 有自己的命名空间,称local namespace,记录函数的变量。

每个模块module 有自己的命名空间,称global namespace,记录模块的变量,包括functions、classes、导入的modules、module级别的变量和常量。

build-in命名空间,它包含build-in function和exceptions,可被任意模块访问。

某段Python代码访问 变量x 时,Python会所有的命名空间中查找该变量,顺序是:

local namespace 即当前函数或类方法。若找到,则停止搜索;

print(sys.modules)#打印,查看该字典具体内容。

每个函数function 有自己的命名空间,称local namespace,记录函数的变量。

每个模块module 有自己的命名空间,称global namespace,记录模块的变量,包括functions、classes、导入的modules、module级别的变量和常量。

build-in命名空间,它包含build-in function和exceptions,可被任意模块访问。

某段Python代码访问 变量x 时,Python会所有的命名空间中查找该变量,顺序是:

local namespace 即当前函数或类方法。若找到,则停止搜索;

global namespace 即当前模块。若找到,则停止搜索;

build-in namespace Python会假设变量x是build-in的函数函数或变量。若变量x不是build-in的内置函数或变量,Python将报错NameError。

对于闭包,若在local namespace找不到该变量,则下一个查找目标是父函数的local namespace。

例:namespace_test.py代码

def func(a=1):

b = 2

print(locals())#打印当前函数(方法)的局部命名空间

'''

locs = locals()#只读,不可写。将报错!

locs['c'] = 3

print(c)

'''

return a+b

func()

glos = globals()

glos['d'] = 4

print(d)

print(globals())#打印当前模块namespace_test.py的全局命名空间[D:youcaihua\test\test.py]文件

import PkgDemo.mod#1

print(locals(),'\n')

import PkgDemo.pkg1#2

print(locals(),'\n')

import PkgDemo.pkg1.pkg1_mod as m1#3

print(locals(),'\n')

import PkgDemo.pkg2.pkg2_mod#4

PkgDemo.mod.getName()#5

print('调用mod.py----', locals(), '\n')

m1.getName()#6

PkgDemo.pkg2.pkg2_mod.getName()#7

#1 后,将PkgDemo、PkgDemo.mod加入sys.modules中,此时可调用PkgDemo.mod的任何类、或函数。当不能调用包PkgDemo.pkg1或pkg2下任何模块。但当前test.py文件Local命名空间中只有 PkgDemo。

执行 #2 后,只是将PkgDemo.pkg1载入内存,sys.modules会有PkgDemo、PkgDemo.mod、PkgDemo.pkg1 三个模块。但PkgDemo.pkg1下的任何模块 都没有自动载入内存,所以在此时:PkgDemo.pkg1.pkg1_mod.getName()将会出错。当前test.py的Local命名空间依然只有PkgDemo。

执行 #3 后,会将pkg1_mod载入内存,sys.modules会有PkgDemo、PkgDemo.mod、PkgDemo.pkg1、PkgDemo.pkg1.pkg1_mod四个模块,此时可执行PkgDemo.pkg1.pkg1_mod.getName()。由于使用了as,当前Local命名空间将另外添加m1(作为PkgDemo.pkg1.pkg1_mod的别名)、当然还有PkgDemo。

执行 #4 后,会将PkgDemo.pkg2、PkgDemo.pkg2.pkg2_mod载入内存,sys.modules中会有PkgDemo、PkgDemo.mod、PkgDemo.pkg1、PkgDemo.pkg1.pkg1_mod、PkgDemo.pkg2、PkgDemo.pkg2.pkg2_mod六个模块,当然:当前Local命名空间还是只有PkgDemo、m1。

#5、#6、#7当然都可正确执行。

三、How to avoid Python circle import error?如何避免Python的循环导入问题?

代码布局、(架构)设计问题,解决之道是:将循环变成单向。采用分层、用时导入、相对导入(层次建议不要超过两个)

注意:在命令行执行Python xx.py、与IDE中执行,结果可能不同。

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表Finclip的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。
上一篇:「运维有小邓」用于云应用程序的ADSelfService Plus多重身份验证
下一篇:解决RTMP推送时间戳问题引起HLS切片不均匀导致手机浏览器播放卡顿的问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~


×