Python 模块和包、文件 五分钟学会Python 模块和包、文件
咸蛋黄派 人气:0一、 模块
1、模块的概念
模块是 Python 程序架构的一个核心概念
- 每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块
- 模块名 同样也是一个 标识符,需要符合标识符的命名规则
- 在模块中定义的 全局变量 、函数、类 都是提供给外界直接使用的 工具
- 模块 就好比是 工具包,要想使用这个工具包中的工具,就需要先 导入 这个模块
2、模块的两种导入方式
(1)import 语句
import 模块名1, 模块名2
提示:在导入模块时,每个导入应该独占一行
import 模块名1 import 模块名2
导入之后
- 通过 模块名. 使用 模块提供的工具 —— 全局变量、函数、类
- 使用 as 指定模块的别名
import 模块名1 as 模块别名 注意:模块别名 应该符合 大驼峰命名法
(2)From…import 语句
- 如果希望 从某一个模块 中,导入 部分 工具,就可以使用
from ... import
的方式 - import 模块名是 一次性把模块中 所有工具全部导入,并且通过 模块名/别名 访问
# 从 模块 导入 某一个工具 from 模块名1 import 工具名
导入之后
- 不需要 通过 模块名.
- 可以直接使用 模块提供的工具 —— 全局变量、函数、类
注意
两个模块,存在 同名的函数,那么 后导入模块的函数,会 覆盖掉先导入的函数
开发时 import 代码应该统一写在 代码的顶部,更容易及时发现冲突
一旦发现冲突,可以使用 as 关键字 给其中一个工具起一个别名
(3)from…import * 语句
# 从 模块 导入 所有工具 from 模块名1 import *
注意
这种方式不推荐使用,因为函数重名并没有任何的提示,出现问题不好排查
3、模块的搜索顺序[扩展]
Python 的解释器在 导入模块 时,会:
- 搜索 当前目录 指定模块名的文件,如果有就直接导入
- 如果没有,再搜索 系统目录
- 在开发时,给文件起名,不要和 系统的模块文件 重名
Python 中每一个模块都有一个内置属性 __file__
可以 查看模块 的 完整路径
示例 import random # 生成一个 0~10 的数字 rand = random.randint(0, 10) print(rand)
注意:
- 如果当前目录下,存在一个 random.py 的文件,程序就无法正常执行了!
- 这个时候,Python 的解释器会 加载当前目录 下的 random.py 而不会加载 系统的 random 模块
4、 name 属性
在实际开发中,每一个模块都是独立开发的,大多都有专人负责
开发人员 通常会在 模块下方 增加一些测试代码
仅在模块内使用,而被导入到其他文件中不需要执行
- name 属性可以做到,测试模块的代码 只在测试情况下被运行,而在 被导入时不会被执行!
- name 是 Python 的一个内置属性,记录着一个 字符串
- 如果 是被其他文件导入的,name 就是 模块名
- 如果 是当前执行的程序 name 是 main
在很多 Python 文件中都会看到以下格式的代码:
# 导入模块 # 定义全局变量 # 定义类 # 定义函数 # 在代码的最下方 def main(): # ... pass # 根据 __name__ 判断是否执行下方代码 if __name__ == "__main__": main()
二、包
1、概念
- 包 是一个 包含多个模块 的 特殊
- 目录目录下有一个 特殊的文件
__init__.py
- 包名的 命名方式 和变量名一致,小写字母 +
- _使用
import 包名
可以一次性导入包中 所有的模块
2、案例演练
- 新建一个 hm_message 的 包
- 在目录下,新建两个文件 send_message 和 receive_message
- 在 send_message 文件中定义一个 send 函数
- 在 receive_message 文件中定义一个 receive 函数
- 在外部直接导入 hm_message 的包
要在外界使用 包 中的模块,需要在__init__.py
中指定 对外界提供的模块列表
# 从 当前目录 导入 模块列表 from . import send_message from . import receive_message
三、发布模块(知道)
如果希望自己开发的模块,分享 给其他人,可以按照以下步骤操作
1、 制作发布压缩包步骤
(1)创建 setup.py setup.py 的文件
from distutils.core import setup setup(name="hm_message", # 包名 version="1.0", # 版本 description="itheima's 发送和接收消息模块", # 描述信息 long_description="完整的发送和接收消息模块", # 完整描述信息 author="itheima", # 作者 author_email="itheima@itheima.com", # 作者邮箱 url="www.itheima.com", # 主页 py_modules=["hm_message.send_message", "hm_message.receive_message"])
(2) 构建模块
$ python3 setup.py build 3) 生成发布压缩包 $ python3 setup.py sdist
注意:要制作哪个版本的模块,就使用哪个版本的解释器执行!
2、安装模块
$ tar -zxvf hm_message-1.0.tar.gz $ sudo python3 setup.py install
卸载模块
直接从安装目录下,把安装模块的 目录 删除就可以
$ cd /usr/local/lib/python3.5/dist-packages/ $ sudo rm -r hm_message*
3、pip 安装第三方模块
- 第三方模块 通常是指由 知名的第三方团队 开发的 并且被 程序员广泛使用 的 Python 包 / 模块
- 例如 pygame 就是一套非常成熟的 游戏开发模块
- pip 是一个现代的,通用的 Python 包管理工具
- 提供了对 Python 包的查找、下载、安装、卸载等功能
安装和卸载命令如下:
# 将模块安装到 Python 2.x 环境 $ sudo pip install pygame $ sudo pip uninstall pygame # 将模块安装到 Python 3.x 环境 $ sudo pip3 install pygame $ sudo pip3 uninstall pygame 在 Mac 下安装 iPython $ sudo pip install ipython 在 Linux 下安装 iPython $ sudo apt install ipython $ sudo apt install ipython3
四、文件
1、文件的基本操作
(1)操作文件的套路
在 计算机 中要操作文件的套路非常固定,一共包含三个步骤:
打开文件
- 读、写文件
- 读 将文件内容读入内存
- 写 将内存内容写入文件
关闭文件
(2)操作文件的函数/方法
在 Python 中要操作文件需要记住 1 个函数和 3 个方法
序号 | 函数/方法 | 说明 |
---|---|---|
01 | open | 打开文件,并且返回文件操作对象 |
02 | read | 将文件内容读取到内存 |
03 | write | 将指定内容写入文件 |
04 | close | 关闭文件 |
- open 函数负责打开文件,并且返回文件对象
- read/write/close 三个方法都需要通过 文件对象 来调用
(3)read 方法 —— 读取文件
open 函数的第一个参数是要打开的文件名(文件名区分大小写) 如果文件 存在,返回 文件操作对象如果文件 不存在,会 抛出异常 read 方法可以一次性 读入 并 返回 文件的 所有内容close 方法负责 关闭文件(如果忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问)
注意:read 方法执行后,会把 文件指针 移动到 文件的末尾
# 1. 打开 - 文件名需要注意大小写 file = open("README") # 2. 读取 text = file.read() print(text) # 3. 关闭 file.close() 提示 在开发中,通常会先编写 打开 和 关闭 的代码,再编写中间针对文件的 读/写 操作!
(4)文件指针(知道)
- 文件指针 标记 从哪个位置开始读取数据
- 第一次打开 文件时,通常 文件指针会指向文件的开始位置
- 当执行了 read 方法后,文件指针 会移动到 读取内容的末尾
- 默认情况下会移动到 文件末尾
思考
如果执行了一次 read 方法,读取了所有内容,那么再次调用 read 方法,还能够获得到内容吗?答案
不能 第一次读取之后,文件指针移动到了文件末尾,再次调用不会读取到任何的内容
(5)打开文件的方式
open 函数默认以 只读方式 打开文件,并且返回文件对象
语法如下:
f = open("文件名", "访问方式")
访问方式 | 说明 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式。如果文件不存在,抛出异常 |
w | 以只写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
a | 以追加方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
r+ | 以读写方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常 |
w+ | 以读写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
a+ | 以读写方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
提示
频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以 只读、只写 的方式来操作文件
写入文件示例
# 打开文件 f = open("README", "w") f.write("hello python!\n") f.write("今天天气真好") # 关闭文件 f.close()
(6) 按行读取文件内容
- read 方法默认会把文件的 所有内容 一次性读取到内存
- 如果文件太大,对内存的占用会非常严重
- readline 方法可以一次读取一行内容
- 方法执行后,会把 文件指针 移动到下一行,准备再次读取
- 读取大文件的正确姿势
# 打开文件 file = open("README") while True: # 读取一行内容 text = file.readline() # 判断是否读到内容 if not text: break # 每读取一行的末尾已经有了一个 `\n` print(text, end="") # 关闭文件 file.close()
(7) 文件读写案例 —— 复制文件
目标
用代码的方式,来实现文件复制过程
小文件复制
打开一个已有文件,读取完整内容,并写入到另外一个文件
# 1. 打开文件 file_read = open("README") file_write = open("README[复件]", "w") # 2. 读取并写入文件 text = file_read.read() file_write.write(text) # 3. 关闭文件 file_read.close() file_write.close()
大文件复制
打开一个已有文件,逐行读取内容,并顺序写入到另外一个文件
# 1. 打开文件 file_read = open("README") file_write = open("README[复件]", "w") # 2. 读取并写入文件 while True: # 每次读取一行 text = file_read.readline() # 判断是否读取到内容 if not text: break file_write.write(text) # 3. 关闭文件 file_read.close() file_write.close()
2、文件/目录的常用管理操作
- 在 终端 / 文件浏览器、 中可以执行常规的 文件 / 目录 管理操作,例如:
- 创建、重命名、删除、改变路径、查看目录内容、……
- 在 Python 中,如果希望通过程序实现上述功能,需要导入 os 模块
文件操作
序号 | 方法名 | 说明 | 示例 |
---|---|---|---|
01 | rename | 重命名文件 os.rename(源文件名, 目标文件名) | |
02 | remove | 删除文件 os.remove(文件名) |
目录操作
序号 | 方法名 | 说明 | 示例 |
---|---|---|---|
01 | listdir | 目录列表 | os.listdir(目录名) |
02 | mkdir | 创建目录 | os.mkdir(目录名) |
03 | rmdir | 删除目录 | os.rmdir(目录名) |
04 | getcwd | 获取当前目录 | os.getcwd() |
05 | chdir | 修改工作目录 | os.chdir(目标目录) |
06 | path.isdir | 判断是否是文件 | os.path.isdir(文件路径) |
提示:文件或者目录操作都支持 相对路径 和 绝对路径
3、Ptyhon 2.x 中如何使用中文
在 Python 2.x 文件的 第一行 增加以下代码,解释器会以 utf-8 编码来处理 python 文件
# *-* coding:utf8 *-*
这方式是官方推荐使用的!
也可以使用
# coding=utf8
unicode 字符串
- 在 Python 2.x 中,即使指定了文件使用 UTF-8 的编码格式,但是在遍历字符串时,仍然会 以字节为单位遍历 字符串
- 要能够 正确的遍历字符串,在定义字符串时,需要 在字符串的引号前,增加一个小写字母 u,告诉解释器这是一个 unicode 字符串(使用 UTF-8 编码格式的字符串)
# *-* coding:utf8 *-* # 在字符串前,增加一个 `u` 表示这个字符串是一个 utf8 字符串 hello_str = u"你好世界" print(hello_str) for c in hello_str: print(c)
五、命名空间和作用域
变量是拥有匹配对象的名字(标识符)。命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典。
一个Python表达式可以访问局部命名空间和全局命名空间里的变量。如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。
- 每个函数都有自己的命名空间。类的方法的作用域规则和通常函数的一样。
- Python会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的。
因此,如果要给全局变量在一个函数里赋值,必须使用global语句。
#!/usr/bin/python # -*- coding: UTF-8 -*- Money = 2000 def AddMoney(): # 想改正代码就取消以下注释: # global Money Money = Money + 1 print Money AddMoney() print Money
1、dir()函数
dir()函数一个排好序的字符串列表,内容是一个模块里定义过的名字。
返回的列表容纳了在一个模块里定义的所有模块,变量和函数。如下一个简单的实例:
#!/usr/bin/python # -*- coding: UTF-8 -*- # 导入内置math模块 import math content = dir(math) print content;
以上实例输出结果:
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan',
'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp',
'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh',
'sqrt', 'tan', 'tanh']
在这里,特殊字符串变量__name__指向模块的名字,__file__指向该模块的导入文件名。
2、globals()和locals()函数
- 根据调用地方的不同,**globals()和locals()**函数可被用来返回全局和局部命名空间里的名字。
- 如果在函数内部调用locals(),返回的是所有能在该函数里访问的命名。
- 如果在函数内部调用globals(),返回的是所有在该函数里能访问的全局名字。
- 两个函数的返回类型都是字典。所以名字们能用keys()函数摘取。
3、reload()函数
当一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次。
因此,如果你想重新执行模块里顶层部分的代码,可以用reload()函数。该函数会重新导入之前导入过的模块。语法如下:
reload(module_name)
在这里,module_name要直接放模块的名字,而不是一个字符串形式。比如想重载hello模块,如下:
reload(hello)
加载全部内容