-
模块:就是Python文件,里面定义了很多的函数、类、变量
一个完整大型的python程序是由模块和包的形式组织起来的,可见模块在python中的重要
性。 -
模块有什么作用
1.在python交互式解释器中操作输入的代码,在退出python时是不会被保存的; 而模块文件中的代码是永久存在的。
2.减少重复代码, 减少工作量(写的量、改的量)、代码更优雅、拿来主义 -
包:Python包实际上是一个目录
# 从包中导入模块时,会先执行__init__.py # __init__.py的作用是初始化模块
-
模块和包名要尽量和内置的模块名不相同, 不然会覆盖内置的模块
1.标准模块(库) 无需安装,python自带,直接导入
import random
2.第三方模块 需要安装
pip install requests
import requests
3.自定义模块 自己写的python文件
1.导入方式导入两次,只执行一次
第一次导入的时候,就会将这个模块加载到内存空间
下一次导入的时候,会查看内存空间有没有这个模块,有的话直接拷贝过来
# # 直接导入 # import string # print(string.digits) # # 导入string里面的digits变量,如果导入的是函数,那么print里面的函数名后面要加括号 # from string import digits # print(digits) # # 导入string模块里面所有的东西 # from string import * # print(digits)
# 方法一 from pack01 import one one.packtest() # 方法二 from pack01.one import packtest packtest() # 导入的第二个会覆盖第一个 from pack01.one import packtest from pack02.one import packtest packtest() # 要想导入两个名字相同的模块,需要起别名 from pack01.one import packtest as pack01test from pack02.one import packtest pack01test() packtest()2.动态导入
import importlib
st = importlib.import_module("string")
print(st.digits)
小练习
# 接收从键盘的输入,实现动态导入模块
# 可以无限制导入,按q退出
# 导入模块之后,输出相应的模块属性dir(),提示相应模块的导入成功
import importlib
while True:
module_name = input("请输入需要导入的模块名:")
if module_name == 'q':
break
else:
module = importlib.import_module(module_name)
print(dir(module))
print(f"{module}导入成功")
3.绝对导入和相对导入
绝对导入
相对导入没有 . 或者 … 的导入就是绝对导入
绝对导入的路径就是从top-level一层一层往下数
from pack01.subpack01 import subpk01
top-level: 哪个模块作为主程序直接运行,那模块所在的目录就是top-level
主程序: mod.py
top-level: mod.py pack01 pack02
四、模块的查找顺序模块路径由 点 开始的导入,就是相对导入
相对导入不能识别到top-level那一层,只能识别到top-level以下层
==两个点代表上一级 …代表上两级
示例:
1.
from …subpack02 import subpk02在mod.py中运行,主程序:mod.py
top-level:mod.py pack01 pack02
不能识别到top-level层,但可以识别到以下层 subpack02
所以在mod.py中可以导入成功
from …pack01.subpack02 import subpk02
在mod.py中运行,主程序:mod.py
top-level:mod.py pack01 pack02
不能识别到top-level层,所以不能识别pack01
所以在mod.py中导入失败
from pack01.subpack02 import subpk02
绝对路径
在mod.py运行,可以导入成功
import sys
print(sys.modules)
查看当前这个程序里面已经加载好的模块
python中所有加载到内存的模块都放在sys.modules。1.当import一个模块时首先会sys.modules在这个列表中查找是否已经加载了此模块
如果加载了则将模块拷贝过来使用
2.如果没有加载就从sys.path目录中按照模块名查找,最先找的是当前目录
如果没有找到模块名就报错print(sys.path)
[root@wh import-test]# vim string.py [root@wh import-test]# python3 Python 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path ['', '/usr/lib64/python36.zip', '/usr/lib64/python3.6', '/usr/lib64/python3.6/lib-dynload', '/usr/local/lib64/python3.6/site-packages', '/usr/local/lib/python3.6/site-packages', '/usr/lib64/python3.6/site-packages', '/usr/lib/python3.6/site-packages'] >>> import string i am string # 在当前目录下找到了string的模块文件 >>> import xx # 没找到模块会报错 Traceback (most recent call last): File "五、python下划线", line 1, in ModuleNotFoundError: No module named 'xx' >>>
标识符是用来标识某种对象的名称。以下划线开头的标识符是有特殊意义的
1.内置属性##########__name__
#一般用于测试的时候,如果自己直接运行,那么__name__就等于__main__,就会执行某些代码,如果别人导入运行,__name__的值就为模块的绝对路径,就不执行那些代码
print(__name__)
# 当模块直接运行的时候,它的值就是__main__
# 当模块导入运行的时候,它的值就是模块的绝对路径
[root@wh import-test]# vim one.py
[root@wh import-test]# python3 one.py
i am one.py
__name__的值为:__main__
执行add函数
3
导入运行时 __name__的值是导入模块的绝对路径
[root@wh import-test]# python3
Python 3.6.8 (default, Nov 16 2020, 16:55:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import one
i am one.py
__name__的值为:one
[root@wh python-test]# ls
import_test test_pass.py
[root@wh python-test]# python3
Python 3.6.8 (default, Nov 16 2020, 16:55:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from import_test import one
i am one.py
__name__的值为:import_test.one
##########__file__
# 打印当前运行模块的路径
print(__file__)
# E:/python project/sanchuang/9)python模块与包/01.模块导入/mod.py
#常用搭配
import os,sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# print(os.path.abspath("..")) 绝对路径
sys.path.append(BASE_DIR)
# E:python projectsanchuang9)python模块与包
2.以下划线开头的变量
以下划线开头的变量或函数或类,是无法被模糊导入的
双下划线开头和双下划线结尾的 都是python里面的特殊标识,有特殊含义
不要使用双下划线开头和双下划线结尾的标识符
from pack02.one import * this is pack02.one print(a) # 1 print(_a) # NameError: name '_a' is not defined print(__a) # NameError: name '__a' is not defined from pack02 import one # this is pack02.one print(one.a) # 1 print(one._a) # 2 print(one.__a) # 3
###########__name__ # 当__init__.py中定义 __all__指定模糊导入 __all__ = ["two","three"] from pack02 import * # * 就是pack02里面的__init__.py里面定义的__all__ # i am __init__.py # this is two # this is three六、python文件执行的过程
七、模块的打包与发布python的执行过程
1.语法分析
2.编译成字节码 .pyc文件
3.对字节码编译成二进制pyc文件
python2 模块导入运行的时候会在同级目录下创建一个pyc文件
python3 模块导入运行的时候会在同级目录下创建一个 pychche_文件夹,pyc文件就放在这里面直接运行的模块,不会将字节码保存
导入运行的模块,会将编译好的字节码保存在磁盘上以.pyc结尾下次再进行导入运行的时候,就直接查看字节码文件即可,不需要在编译成字节码
改动了模块,下次运行字节码会重新编译
#使用setuptools工具
#####打包步骤
#1.创建模块包 sanle 需要一个__init__.py文件
[root@wh modpack]# cd sanle/
[root@wh sanle]# ls
__init__.py sanchuang.py
[root@wh sanle]# cat sanchuang.py
print("this is sanchuang")
def func1():
print("this is func1")
#2.在sanle同级目录下创建打包配置文件setup.py
[root@wh modpack]# cat setup.py
from setuptools import setup,find_packages
setup(
#包名
name = "sc",
#官网
url = "http://www.sanchuangedu.cn",
#版本号
version = "0.0.1",
#指定要打包的模块和包
packages = find_packages(),
#作者
author = "wh",
#作者邮箱
author_email = "1968084441@qq.com",
#依赖
install_requires = ['xlrd>=1.1.0'],
#描述信息
description = "this is test package"
)
# 3.运行python3 setup.py check 进行语法检查
# 4.运行python3 setup.py sdist 生成.tar.gz压缩包
#会在同级目录下生成一个dist目录
# 5.安装
#进入dist目录
#pip install sc-0.0.1.tar.gz
[root@wh modpack]# ls
dist sanle sc.egg-info setup.py
[root@wh modpack]# cd dist/
[root@wh dist]# ls
sc-0.0.1.tar.gz
[root@wh dist]# pip3 install sc-0.0.1.tar.gz
#6.测试
```bash
[root@wh dist]# python3
Python 3.6.8 (default, Nov 16 2020, 16:55:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from sanle import sanchuang
this is sanchuang
>>> sanchuang.func1()
this is func1



