五分钟学会Python 模块和包、文件
一、 模块
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)
到此这篇关于五分钟学会python 模块和包、文件的文章就介绍到这了,更多相关python 模块和包、文件内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!