python模块的导入

一、模块的简介

1、什么是模块

  Python 模块是一个 Python 文件,定义了各种功能接口。

2、为啥使用模块

  把复杂的功能封装为模块(又称为库),将功能实现的细节隐藏起来,使用该模块(库)的程序员不需要了解实现的细节。通过调用模块封装好的功能,

可以用仅仅几行 Python 代码实现某项复杂的功能,例如可以用一行代码就实现一个 Web 服务器。

3、模块的来源

  • 内置的(python解释器自带的直接用,eg:time)
  • 第三方的(别人写好的放在网上的,我们要想用,必须先下载才能用)
  • 自定义的(我们自己写的,以后也可以传到网上去)

4、在Python中,总共有以下四种形式的模块:

  • 自定义模块:如果你自己写一个py文件,在文件内写入一堆函数,则它被称为自定义模块,即使用python编写的.py文件
  • 第三方模块:已被编译为共享库或DLL的C或C++扩展
  • 内置模块:使用C编写并链接到python解释器的内置模块
  • 包:把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)

5、模块与包

模块:

  一个py文件,被别的py文件导入使用,这个py文件称之为模块,运行的这个py文件称之为脚本文件

  - s1 自己点右键运行,这个文件s1叫脚本文件

  - 在s2中,把s1,引入使用,s1就叫模块

包:

  一个文件夹下有__init__.py -作用:包内部的函数,类..想给外部方便使用(导入的时候路径短一些,就要在里面做注册)

6、模块与包的导入问题

导入模块有相对导入和绝对导入,绝对的路径是从环境变量开始的

导入任何模块,如果使用绝对导入,都是从环境变量开始导入起

  import xx #### xx所在路径必须在环境变量

  from yy import ####yy所在路径必须在环境变量中

脚本文件执行的路径,会自动加入环境变量

相对导入的话,是从当前py文件开始计算的

以脚本运行的文件,不能使用相对导入,只能用绝对导入

7、包中的__init__.py 作用

标识该文件夹为包

初始化包级别的操作:

  • 您可以在 __init__.py 文件中执行一些初始化工作,例如设置包级别的变量、加载子模块或执行其他必要的初始化代码。

控制导入的内容:

  • 可以在 __init__.py 文件中定义 __all__ 变量来控制包导入时哪些模块或变量会被默认导入。

提供包级别的文档 

  • 您可以在 __init__.py 文件中提供关于包的文档字符串,以描述包的用途和功能。

导入子模块和子包

  • __init__.py 文件中,您可以导入包内的子模块或子包,以便在导入包时可以直接访问它们。
  • # __init__.py
    from . import module1
    from . import subpackage1

二、模块的导入

1、导入语法

import 句式

首次导入文件,会执行导入文件的代码
导入文件不管你导入几次,都只执行一次
导入文件的过程发生了什么事?
1. 运行执行文件,产生执行文件的全局名称空间
2. 运行md.py文件,会产生md文件的全局名称空间,把md文件里的名字都丢到md的全局名称空间去
3. 在执行文件中有一个md的变量,指向导入文件的空间地址
4. 以后我们在执行文件中就可以用md来点出导入文件中的名字
  导入文件之后,以后在用导入文件中的名字,只需要使用md点语法的形式点出来就可以
  不会与执行文件中的名字发生冲突,因为我们是指名道姓的取值

from 模块名 import *”

from md import money,read1,read2  # 一个模块下的不同函数,连续导入直观

通用导入

# from md import money, read1, read2, change,
from 模块名 import *

2、起别名

import xxx as xx

from xxx import xx as x

3、设置禁止被导用的部分模块功能

方式1:

设置私有属性

单下划线“_”或者双下划线“__”开头的变量、函数和类

##  导入文件
def say():
    print("人生苦短,我学Python!")
def CLanguage():
    print("C语言中文网:http://c.biancheng.net")
def _disPython():
    print("Python教程:http://c.biancheng.net/python")


##执行文件
from example import *
say()
CLanguage()
disPython()

方式2:

只有以“from 模块名 import *”形式导入的模块,当该模块设有 __all__ 变量时,只能导入该变量指定的成员,未指定的成员是无法导入的。

## 导入文件
def say():
    print("人生苦短,我学Python!")
def CLanguage():
    print("C语言中文网:http://c.biancheng.net")
def disPython():
    print("Python教程:http://c.biancheng.net/python")
__all__ = ["say","CLanguage"]


## 执行文件
from example import *
say()
CLanguage()
disPython()

###以“import 模块名”的形式导入模块,__all__ 变量即便设置,也形同虚设。
import example
example.CLanguage()
example.disPython()
example.say()


### 以“from 模块名 import 成员”的形式直接导入指定成员。使用此方式导入的模块,__all__ 变量即便设置,也形同虚设。
from example import say
from example import CLanguage
from example import disPython
say()
CLanguage()
disPython()

4、模块的查找顺序

先在内存中查找

实验:在执行文件中调用导入的模块功能,10秒内删除被导入模块,依然能从内存中读取到数据

import example as e
import  time

time.sleep(10)

e.say()

再从内置模块中查找

从环境变量中查找(sys.path)

### 查看环境变量
import  sys
print(sys.path)

[
'/Users/sanpangdan/Desktop/python_fullstack',  # 当前文件路径

'/Users/sanpangdan/Library/Python/3.6/lib/python/site-packages/_pdbpp_path_hack', 

'/Users/sanpangdan/Desktop/python_fullstack', 

'/Applications/PyCharm.app/Contents/plugins/python/helpers/pycharm_display', 

'/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', 

'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6',
 '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', 

'/Users/sanpangdan/Library/Python/3.6/lib/python/site-packages', 

'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages', 

'/Applications/PyCharm.app/Contents/plugins/python/helpers/pycharm_matplotlib_backend'
]

环境变量存在一个列表里面,注意:

sys.path列表中的第一个元素永远是:当前文件所在的路径
sys.path列表中的第二个元素是:项目的路径,他是pycharm给你加的

如何解决自定义的模块查找不到的问题:

1. 把路径添加到sys.path中去

 sys.path.append(r'D:\python26\day19\aaa')
    import m3
    print(m3.name)

2. 使用相对导入或者绝对导入

from 模块1.模块2.模块3 import...句式

绝对导入

"""当导入多个模块的时候,要始终以执行文件所在的位置为基准"""

绝对导入:
    始终以执行文件所在的位置查找

相对导入

 使用的符号是.
        句点符(.)
            . 表示当前路径
            .. 表示的是上一级目录
    
# 相对导入就可以不按照执行文件所在的位置为基准,而只参照当前文件所在的位置
   
# 当文件中出现相对导入的语句,此文件就不能作为执行文件了,只能作为导入文件使用

以上都找不到,则报错

三、importlib动态导入模块

1、如果当我们需要在程序的运行过程时才能决定导入某个文件中的模块时,并且这些文件提供了同样的接口名字,这时候需要使用python 的动态导入。

params.py

i = 1
j = 2
k = 3
 
def add(a, b):
    return a + b
 
def prin():
    print("happy day!")

2、params_get.py

import importlib
 
# 由于 params.py 和 params_get.py 在同一目录下,直接写文件名即可
params = importlib.import_module('params')  
 
# 如果前面加点,则明确表示相对路径,需要加入package参数如下:(params.py我放在了study包中)
# params = importlib.import_module('.params', package='study')  # # study/params.py
 
# 针对网上说的不能放在不同目录下做了测试,发现并没有问题,指明所在包即可
# params = importlib.import_module('.params', package='core')  # core/params.py
# params = importlib.import_module('.params', package='core.test') # core/test/params.py
 
print(params.i, params.j, params.k)  # 1 2 3
 
print(params.add(4, 5))  # 9
 
params.prin()  # happy day!

补充:避免循环导入问题

1、使用“import as”语法

2、使用importlib动态导入

3、创建一个通用文件,从该文件导入

4、在函数局部导入

5、传递所需的对象或函数作为参数,而非直接在模块中导入

四、if __name__ == '__main__':的理解

1、目的

__name__为Python 内置的系统变量,它用于标识所在模块的模块名。在没有导入外部模块时,__name__默认值为__main__。而导入到当前程序中的模块,其 __name__ 值为自己的模块名。

具体来说,当一个Python文件被执行时,Python解释器会将该文件中的所有代码都执行一遍,包括定义函数、变量等等。而当一个模块被导入到另一个程序中时,该模块中的所有代码也会被执行一遍,这可能会导致一些不必要的问题。

为了避免这种情况,我们可以使用if __name__ == '__main__':代码块。这个代码块中的代码只有在该文件作为主程序运行时才会被执行,而当该文件被作为模块导入时,这个代码块中的代码不会被执行。

2、案例

# example.py 导入文件
print('from example.py')

def my_function():
    print(__name__)

if __name__ == '__main__':
    my_function()

## test.py 执行文件
import example as e
# e.my_function()
print(__name__

结果:执行文件导入example模块,

my_function函数没有执行

print('from example.py') 立即执行

因为my_function函数做了 if __name__ == '__main__':条件判断,不会立马执行

要想执行被导入的函数,在执行文件中直接调用,没有了if条件,即可调用成功

import example as e
e.my_function()
print(__name__)

 

posted @ 2023-06-06 15:23  凡人半睁眼  阅读(82)  评论(0编辑  收藏  举报