文件操作与模块和包
本篇要点:① 文件读写与备份 ② OS 模块(文件/目录操作) ③ time 模块 ④ 模块与包(导入、自定义、常见问题)
大纲
- 文件操作(打开/关闭、读、写、备份案例、with)
- OS 模块(操作文件、操作目录)
- time 模块(时间戳、运行耗时)
- 模块和包(导入方式、random 模块、自定义模块与包)
一、文件操作
文件的打开和关闭
properties
open函数参数1 file: 文件路径
绝对路径: 以盘符开头的路径
相对路径: 不以盘符开头的路径 .当前目录 ..上一级目录
open函数参数2 mode: 文件模式
r: 读(默认) rb:二进制读 特点: 文件必须存在,否则报错
w: 写 wb:二进制写 特点: 文件如果存在就使用,不存在就创建
a: 追加 ab:二进制追加写 特点: 文件如果存在就使用,不存在就创建
open函数参数3 encoding: 文件编码
注意: 二进制相关模式不需要文件编码,否则报错
gbk: 主要针对中文扩展,又叫cp936
utf8: 通用编码,又叫万国码python
# 1.打开文件
f = open('word.txt', mode='r', encoding='utf8')
# 2.读写文件
# 3.关闭文件
f.close()文件的读操作
properties
读模式:
r: 读非二进制格式数据
rb: 读二进制格式数据
字符串转二进制: 字符串.encode(编码)
二进制转字符串: 二进制.decode(编码)
一个个读:
read(num): 读n个字符
read(): 读剩下的所有字符
一行行读:
readline(): 读一行
readlines(): 读剩下的所有行(默认放到列表中返回)python
# 注意: 如果读取非文本文件,则需要指定mode='rb',且不能添加encoding参数
f = open('word.txt', 'r', encoding='utf8')
# 方式1: read(num) 读取指定num个字符
# content = f.read(7)
# 方式2: read() 默认读取所有字符
content = f.read()
print(content)
# 方式3: readline() 读取一行
# 方式4: readlines() 一次性读取所有行
f.close()文件的写操作
properties
写模式:
w: 非二进制格式数据,覆盖写
a: 非二进制格式数据,追加写
ab: 二进制格式数据,追加写
一个个写: write(内容)
一行行写: writelines(内容)python
f = open('new_word.txt', 'w', encoding='utf8')
f.write('hello world\n')
f.writelines(['你好\n', 'python\n', '文件操作\n'])
f.close()文件的备份综合案例
文本文件/任意文件的备份
python
# 分析: 要完成任意文件,读写模式都应该选择通用的二进制模式
f_in = open('sources/file.mp4', 'rb')
f_out = open('backup/file[备份].mp4', 'wb')
# 先读取源文件
data = f_in.read()
# 再把源文件数据写入到备份文件
f_out.write(data)
# 关闭文件: 先开后关
f_out.close()
f_in.close()函数优化版
python
def file_copy(in_path):
i = in_path.rfind('.')
if i == -1:
print('对不起,您输入的文件路径无效!!!')
else:
out_path = in_path[:i] + "[备份]" + in_path[i:]
f1 = open(in_path, 'rb')
f2 = open(out_path, 'wb')
data = f1.read()
f2.write(data)
f2.close()
f1.close()
in_path = input('请您输入要备份的文件路径:')
file_copy(in_path)补充:with open 方式
python
# f = open(): 必须手动关闭文件,也可能受异常影响导致没有执行到关闭代码
# with open() as f: 自动关闭文件,不会受异常影响
with open('sources/word.txt', 'r', encoding='utf8') as f_in:
data = f_in.read()
print(data)二、OS 模块
简介
os 模块是 Python 标准库的一部分,提供了丰富的功能与操作系统进行交互,如文件重命名、文件删除、获取当前工作目录、创建和删除目录、检查文件或目录是否存在等。
python
import os
# 获取环境变量(先系统变量然后用户变量)
print(os.getenv("PATH"))
# 由于api很多不要试图去记忆,学会os.查找函数操作文件
| 编号 | 函数 | 功能 |
|---|---|---|
| 1 | os.rename(目标文件名,新文件名) | 对文件进行重命名操作 |
| 2 | os.remove(要删除文件名) | 对文件进行删除操作 |
python
import os
# 注意: 要修改或者删除的文件一定要存在
os.rename('sources/new_word.txt', 'sources/new_word_rename.txt')
os.remove('sources/new_word_rename.txt')操作目录
| 编号 | 函数 | 功能 |
|---|---|---|
| 1 | os.mkdir(新文件夹名称) | 创建指定名称的文件夹 |
| 2 | os.getcwd() | 获取当前目录名称 |
| 3 | os.chdir(切换后目录名称) | 切换目录 |
| 4 | os.listdir(目标目录) | 获取指定目录下的文件信息,返回列表 |
| 5 | os.rmdir(目标目录) | 删除指定名称的"空"文件夹 |
python
import os
# 获取当前工作目录
print(os.getcwd())
# 切换工作目录
os.chdir('static')
print(os.getcwd())
# 创建目录
os.mkdir('images')
os.mkdir('videos')
# 获取目录下所有文件和文件夹
print(os.listdir())
# 移除文件夹(rmdir只能删除空目录)
os.rmdir('videos')
# 删除非空目录可以用 shutil.rmtree()
import shutil
shutil.rmtree('static')补充:os 模块完整 API 参考
1. 目录操作
| 函数 | 说明 |
|---|---|
| os.getcwd() | 返回当前工作目录的字符串 |
| os.chdir(path) | 将当前工作目录更改为 path |
| os.listdir(path='.') | 返回指定目录下所有文件和目录名的列表 |
| os.mkdir(path, mode=0o777) | 创建单层目录,已存在则抛 FileExistsError |
| os.makedirs(path, exist_ok=False) | 递归创建多层目录,exist_ok=True 时不报错 |
| os.rmdir(path) | 删除空目录 |
| os.removedirs(path) | 递归删除空目录,直到遇到非空目录 |
| os.rename(src, dst) | 重命名文件或目录(也可移动文件) |
| os.stat(path) | 获取文件/目录状态信息(大小、修改时间等) |
2. 文件操作
| 函数 | 说明 |
|---|---|
| os.remove(path) | 删除文件 |
| os.unlink(path) | 同 os.remove() |
| os.replace(src, dst) | 重命名,目标存在则覆盖(跨平台) |
| os.path.getsize(path) | 获取文件大小(字节) |
| os.path.getmtime(path) | 获取最后修改时间(时间戳) |
3. 路径操作(os.path 模块)
| 函数 | 说明 |
|---|---|
| os.path.join(a, *p) | 智能拼接路径,自动使用当前系统分隔符 |
| os.path.exists(path) | 判断路径是否存在 |
| os.path.isfile(path) | 判断路径是否为文件 |
| os.path.isdir(path) | 判断路径是否为目录 |
| os.path.abspath(path) | 返回绝对路径 |
| os.path.basename(path) | 返回路径中的文件名部分 |
| os.path.dirname(path) | 返回路径中的目录部分 |
| os.path.split(path) | 拆分路径为 (目录, 文件名) 元组 |
| os.path.splitext(path) | 拆分路径为 (根, 扩展名) 元组 |
4. 遍历目录树(os.walk)
os.walk(top) 生成目录树中所有文件路径,返回三元组 (dirpath, dirnames, filenames),用于递归遍历。
python
import os
for root, dirs, files in os.walk('.'):
for file in files:
print(os.path.join(root, file))5. 其他常用
| 函数 | 说明 |
|---|---|
| os.environ | 访问环境变量的字典 |
| os.sep | 当前系统的路径分隔符(\ 或 /) |
| os.linesep | 当前系统的换行符 |
| os.system(command) | 执行操作系统命令(不推荐,建议用 subprocess) |
6. 综合演示
python
import os
cwd = os.getcwd()
print("当前目录:", cwd)
os.makedirs("test_dir/sub_dir", exist_ok=True) # 创建目录
os.chdir("test_dir")
print("切换后目录:", os.getcwd())
with open("example.txt", "w") as f: # 创建文件并写入
f.write("Hello, World!")
print("目录内容:", os.listdir())
if os.path.exists("example.txt"): # 检查文件是否存在
print("文件大小:", os.path.getsize("example.txt"), "字节")
os.rename("example.txt", "new_example.txt") # 重命名
os.remove("new_example.txt") # 删除文件
os.chdir("..")
os.removedirs("test_dir/sub_dir") # 删除目录树(需先清空内容)注意事项
- 使用 os.remove() 和 os.rmdir() 时要确保文件/目录存在且权限正确。
- 操作路径时推荐使用 os.path.join() 避免跨平台问题。
- 更高级的文件操作(复制、移动、删除非空目录)建议使用 shutil 模块。
三、time 模块
入门案例
python
import time
import datetime
# 获取当前时间戳: 1970年1月1日0时0分0秒到当前时间的秒数
print(time.time()) # 重点!!!
print(time.localtime())
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
# datetime 方式
print(datetime.datetime.now())
print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))计算程序运行时间
python
import time
start = time.time()
print("开始时间:", start)
# 累加计算1到1亿的数字之和
sum = 0
for i in range(1, 100000001):
sum += i
print(f"总和:{sum}")
end = time.time()
print("程序运行时间:", end - start)四、模块和包
模块概念
Python 模块(Module)是一个 Python 文件,以 .py 结尾。模块能定义函数、类和变量,模块里也能包含可执行的代码。 模块的作用:python 中有很多不同的模块,每个模块都可以帮助我们快速实现一些功能(如 time 模块实现时间相关功能)。可以认为一个模块就是一个工具包。
导入模块
properties
import方式
import 包名.模块名 [as 别名]
import 模块名 [as 别名]
from方式
from 包名 import 模块名 [as 别名]
from 模块名 import 功能名 [as 别名]
from 包名.模块名 import 功能名 [as 别名]python
# import方式导入模块
import random
print(random.randint(1, 5))
# from方式导入模块中指定功能
from random import randint
print(randint(1, 5))
# from方式导入模块中所有功能
from random import *
print(choice('abc_123'))
print(sample('abc_123', 2))
# import起别名方式
import random as r
print(r.randint(1, 5))
# from起别名方式
from random import randint as rint
print(rint(1, 5))体验 random 模块
random 模块:python 一个具有多种随机功能的内置 python 文件。 使用步骤:1.导包 import random 2.调用 random.函数名(参数)
python
# 需求: 随机生成验证码
import random
s = '1234567890_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
# 方式1: 用sample取4个字符
l1 = random.sample(s, 4)
yzm1 = ''.join(l1)
print(yzm1)
# 方式2: 随机4次,用choice每次取一个字符,然后拼接
yzm2 = ''
for i in range(4):
yzm2 += random.choice(s)
print(yzm2)
# 方式3: 随机4次,用randint每次取一个索引,然后通过索引取字符
yzm3 = ''
for i in range(4):
index = random.randint(0, len(s) - 1)
yzm3 += s[index]
print(yzm3)拓展:string / math 模块
python
# string模块: 快速生成字母数字下划线组成的字符串
import string
zm = string.ascii_letters
sz = string.digits
s = zm + sz + '_'
# math模块
import math
print(math.pi) # 圆周率
print(math.sqrt(9)) # 开方
print(math.pow(2, 3)) # 幂
print(math.log10(100)) # 对数自定义模块和包
properties
包: 本质就是目录,但此目录中必须有一个__init__.py文件管理模块
模块: 本质就是一个py文件,但文件名必须符合标识符命名规则
模块名命名规则: 由字母,数字,下划线组成,不能以数字开头,不能是关键字,严格区分大小写自定义模块(my_m1)
python
def add(a, b):
print('my_m1中add函数被调用了...')
print(a + b)
# 测试的时候没有注释,别人导包的时候就会执行,如何解决?
# 解决方案: 添加main判断
# 当前文件运行__name__值是__main__,其他文件运行__name__值是模块名
if __name__ == '__main__':
add(1, 2)all 列表(my_m3)
python
# 注意: 如果没有__all__列表,from my_m3 import * 默认导入所有功能
# 设置__all__列表,指定哪些功能可以被 from my_m3 import * 导入
__all__ = ['show1', 'show2', 'show3']
def show1():
print('my_m3中show1函数被调用了...')
def show4():
print('my_m3中show4函数被调用了...') # 不在__all__中,不会被导入自定义包

python
# 包的__init__.py文件
# 如果__init__.py中没有__all__列表,from 包 import * 方式不生效
__all__ = ['my_m4', 'my_m5'] # 只能导入__all__列表中的模块常见问题
导入模块中功能
python
# 问题1: 如果my_m1中调用函数时没有添加main判断,导包的时候就会自动调用执行
import my_m1
my_m1.add(3, 4)
# 问题2: 如果用from方式从多个模块导入同名功能,默认就近原则用最后导入的功能
from my_m1 import add
from my_m2 import add
add(3, 4) # 使用的是my_m2的add
# 问题3: 如果模块中设置了__all__列表,则from方式只能导入此列表中指定功能
from my_m3 import *
show1()
show2()
show3()
# show4() # 报错,因为__all__列表没有指定导入包中模块功能
python
# from 包名 import 模块名
from my_package import my_m4
my_m4.test()
# import 包名.模块名
import my_package.my_m4
my_package.my_m4.test()
# from 包 import * : 必须配合__init__.py中的__all__列表使用
from my_package import *
my_m4.test()
my_m5.test()
# my_m6.test() # 报错,因为__all__列表没有指定my_m6模块