第十五章:内置模块(os、sys、json、pickle)
os 模块(重要)
os 模块是与代码所在的操作系统交互的一个接口
文件操作
命令 | 输出 | 描述 |
---|---|---|
os.makedirs(r'E:\tools\test\down') | 可生成多层递归目录 | |
os.removedirs(r'E:\tools\test\down') | 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 | |
os.mkdir(r'E:\tools\test\down\ysg') | 生成单级目录;相当于 shell 中 mkdir dirname | |
os.rmdir(r'E:\tools\test\down\ysg') | 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname | |
s = os.listdir(r'E:\tools') | ['123.xls', 'download', 'download.zip' ... ] | 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 |
os.remove(r'E:\tools\H03668.day') | 删除一个文件 | |
os.rename(r'E:\tools\H03668.day',r'E:\tools\03668.day') | 重命名文件/目录 | |
s1 = os.stat(r'E:\tools\H03668.day') | os.stat_result(st_mode=33206, ...) | 获取文件/目录信息 |
os.walk(r'E:\tools') | ('E:\tools\download', ['zt'], []) | 文件遍历 |
os.stat() 返回属性说明
st_mode: inode 保护模式
st_ino: inode 节点号
st_dev: inode 驻留的设备
st_nlink: inode 的链接数
st_uid: 所有者的用户 ID
st_gid: 所有者的组ID
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据
st_atime: 上次访问的时间
st_mtime: 最后一次修改的时间
st_ctime: 由操作系统报告的"ctime",在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如 Windows)是创建时间(详细信息参见平台的文档)
类命令操作
命令 | 输出 | 描述 |
---|---|---|
os.system("ipconfig") | 运行命令行命令,并显示结果,与 pycharm 的编码格式有关 | |
os.popen('ipconfig').read() | 运行命令行命令,并显示结果,与 pycharm 的编码格式无关 | |
os.getcwd() | E:\tools | 获取当前工作目录,即当前 python 脚本工作的目录路径,相当于 shell 中的 pwd |
os.chdir('..') | 改变当前脚本工作目录;相当于 shell 下 cd |
os.path
数据参数
path = r'E:\tools\H03668.day'
path1 = r'F:\config.ini'
path2 = r'E:\tools'
path3 = r'mysql'
命令 | 输出 | 描述 |
---|---|---|
p = os.path.abspath('.') | Y:\py\use | 返回 path 规范化的绝对路径 |
p1 = os.path.split(path) | ('Y://py//use//czx//one', 'qw') | 将 path 分割成目录和文件名二元组返回 |
p2 = os.path.dirname(path) | Y://py//use//czx//one | 返回 path 的目录 |
p3 = os.path.basename(path) | qw | 返回 path 最后的文件名(可返回空) |
p4 = os.path.exists(path) | True | path 存在,返回 True(或 False) |
p5 = os.path.isabs('.') | False | 如果 path 是绝对路径,返回 True |
p6 = os.path.isfile(path) | False | path 是存在的文件,返回 True(或 False) |
p7 = os.path.isdir(path) | True | path 是存在的目录,返回 True(或 False) |
p8 = os.path.getsize(path1) | 6656 | 返回 path 的大小 |
p9 = os.path.getatime(path) | 1665369606.441087 | 返回 path 所指向的文件或者目录的 最后访问时间 |
p10 = os.path.getctime(path) | 1666171187.7370238 | 返回 path 所指向的文件或者目录的 创建时间 |
p11 = os.path.getmtime(path) | 1665369589.5532897 | 返回 path 所指向的文件或者目录的 最后修改时间 |
p12 = os.path.join(path2,path3) | E:\tools\mysql | 路径拼接,第一个绝对路径之前的参数将被忽略 |
os 模块属性
命令 | 输出 | 描述 |
---|---|---|
os.sep | win下为 "\\" Linux下为 "/" | 输出操作系统特定的路径分隔符 |
os.linesep | win下为 "\r\n" Linux下为 "\n" | 输出当前平台使用的行终止符 |
os.pathsep | win下为 “;” Linux下为 ":" | 输出用于分割文件路径的字符串 |
os.name | win -> 'nt' Linux -> 'posix' | 输出字符串指示当前使用平台 |
sys 模块
sys 模块是与 python 解释器交互的一个接口
sys.argv 返回 List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时 exit(0),错误退出 sys.exit(1)
sys.version 获取 Python 解释程序的版本信息
sys.path 返回模块的搜索路径,初始化时使用 PYTHONPATH 环境变量的值
sys.platform 返回操作系统平台名称
sys.getrecursionlimit() 获取 python 解释器默认最大递归深度
sys.setrecursionlimit(2000) # 修改 python 解释器默认最大递归深度
sys.argv 的例子:
# 命令行执行>>> python test.py ysg 123
# test.py 文件内容
import sys
res = sys.argv
if len(res) != 3:
print('执行命令缺少了用户名或密码')
else:
username = res[1]
password = res[2]
if username == 'ysg' and password == '123':
print('{} 您好,文件正常执行'.format(username))
else:
print('您不是 {} 无权执行该文件'.format(username))
json 模块(重要)
dumps(序列化方法)、loads(反序列化方法),这两个直接对 内存中的数据进行操作
json 本身是单引号的,内部原本是字符串元素要用双引号
dumps() 与 loads()
dumps()
dumps 参数
参数 | 描述 |
---|---|
sort_keys=True | 排序 |
indent | 整齐打印,填充物为空格 |
separators=() | 紧凑编码 |
ensure_ascii=False | 输出为中文,(中文显示默认为 ascii 码) |
例子:
import json
data = {'username': ['张三', '李四'], 'sex': 'male', 'age': 16}
json_dic2 = json.dumps(data, sort_keys=True, indent=4, separators=(',', ':'), ensure_ascii=False)
print(json_dic2)
# {
# "age":16,
# "sex":"male",
# "username":[
# "张三",
# "李四"
# ]
# }
字典与序列化的比较
import json
dic = {"k": 'v'}
print(type(dic), dic) # 输出结果:<class 'dict'> {'k': 'v'}
str_d = json.dumps(dic) # 序列化
print(type(str_d), str_d) # 输出结果:<class 'str'> {"k": "v"}
loads()
import json
dic = {"k": 'v'}
str_d = json.dumps(dic) # 序列化 输出结果:<class 'str'> {"k": "v"}
dic_d = json.loads(str_d) # 反序列化
print(type(dic_d), dic_d) # 输出结果:<class 'dict'> {'k': 'v'}
元组也可以序列化(但被当做列表处理了)
import json
dic = (1, 2, 3)
print(type(dic), dic) # <class 'tuple'> (1, 2, 3)
str_d = json.dumps(dic)
print(type(str_d), str_d) # <class 'str'> [1, 2, 3]
dic_d = json.loads(str_d)
print(type(dic_d), dic_d) # <class 'list'> [1, 2, 3]
dump() 与 load()
dump(序列化方法)、load(反序列化方法),这两个是 对文件相关的操作
dump load 一次性写入 一次性读出
import json
dic = {1: "a", 2: "b"}
with open('E:/tools/file.txt', 'w', encoding='utf-8') as fw:
ret = json.dump(dic, fw)
print(type(ret), ret) # <class 'NoneType'> None
with open('E:/tools/file.txt', encoding='utf-8') as fr:
res = json.load(fr)
print(type(res), res) # <class 'dict'> {'2': 'b', '1': 'a'}
json 模块实战
# 使用 json 文件,实现用户 登录与注册 功能
def sign_in(db_dir):
username = input('username>>>:').strip()
target_user_file_path = os.path.join(db_dir, '{}.json'.format(username))
if not os.path.isfile(target_user_file_path):
print('用户名不正确')
else:
password = input('password>>>:').strip()
# 2.获取用户真实数据字典
with open(target_user_file_path, 'r', encoding='utf-8') as f:
real_user_dict = json.load(f)
if password == real_user_dict.get('password'):
print('登录成功')
else:
print('密码错误')
def register(db_dir):
username = input('username>>>:').strip()
password = input('password>>>:').strip()
dic = {'username': username, 'password': password}
with open(os.path.join(db_dir, '{}.json'.format(username)), 'w', encoding='utf-8') as fw:
json.dump(dic, fw)
pass
def run():
db_dir = os.path.join(os.getcwd(), 'db')
print(db_dir)
if not os.path.exists(db_dir):
os.mkdir(db_dir)
while 1:
info = '''
1.登录
2.注册
'''
print(info)
num = input('>>>').strip()
if num == '1':
sign_in(db_dir)
elif num == '2':
register(db_dir)
else:
print('已退出')
return
if __name__ == '__main__':
run()
pickle 模块(非常不常用)
用法与 json 模块一致,但是只用于 python,无法兼容其它语言,且只能与要存储的 python 对象在同一文件中使用。
它能够实现任意对象与文本之间的相互转化,也可以实现任意对象与二进制之间的相互转化。也就是说,pickle 可以实现 Python 对象的存储及恢复。
pickle 模块提供了以下 4 个函数供我们使用:
- dumps():将 Python 中的对象序列化成二进制对象,并返回对象
- loads():读取给定的二进制对象数据,并将其转换为 Python 对象
- dump():将 Python 中的对象序列化成二进制对象,并写入文件
- load():读取指定的序列化数据文件,并返回对象
# dumps() 和 loads() 是基于内存的 python 对象与二进制互转
# dump() 和 load() 是基于文件的 python 对象与二进制互转
存储 list 对象
import pickle
list = [1, 2, 3, 12, 41]
with open('pickle_lit1', 'wb') as fw:
pickle.dump(list, fw)
with open('pickle_lit1', 'rb') as fr:
ret = pickle.load(fr)
print(ret)
存储 class 对象
class Test:
def __init__(self, name, age):
self.name = name
self.age = age
def func1(self):
print('this is func1')
t = Test('ysg', '25')
# 存储 Test 类
with open('pickle_class', 'wb') as fw:
pickle.dump(Test, fw)
with open('pickle_class', 'rb') as fr:
ret = pickle.load(fr)
r = ret('ysg', 25)
print(ret) # <class '__main__.Test'>
print(r.name) # ysg
print(r.age) # 25
r.func1() # this is func1
# 存储实例化后的 t 对象
with open('pickle_class', 'wb') as fw:
pickle.dump(t, fw)
with open('pickle_class', 'rb') as fr:
ret = pickle.load(fr)
print(ret) # <__main__.Test object at 0x015B3F88>
print(ret.name) # ysg
print(ret.age) # 25
ret.func1() # this is func1
作业
1.编写一个统计指定文件类型的脚本工具
输入指定类型的文件后缀
eg:.txt
并给出一个具体路径 之后统计该类型文件在该文件下的个数
ps:简单实现即可 无需优化
2.针对json实操 尝试单文件多用户(一行一个)是否可实现>>>:哪个更方便
不要求完成 单纯体会两种思路的难易
3.编程小练习
有一个目录文件下面有一堆文本文件
eg:
db目录
J老师视频合集
R老师视频合集
C老师视频合集
B老师视频合集
文件内容自定义即可 要求循环打印出 db 目录下所有的文件名称让用户选择
用户选择哪个文件就自动打开该文件并展示内容
涉及到文件路径全部使用代码自动生成 不准直接拷贝当前计算机固定路径
4.周末大作业(尝试编写)
# 项目功能
1.用户注册
2.用户登录
3.添加购物车
4.结算购物车
# 项目说明
用户数据采用json格式存储到文件目录db下 一个用户一个单独的文件
数据格式 {"name":"jason","pwd":123}
# ps:文件名可以直接用用户名便于校验
用户注册时给每个用户添加两个默认的键值对(账户余额 购物车)
{"balance":15000,"shop_car":{}}
添加购物车功能 商品列表可以自定义或者采用下列格式
good_list = [
['挂壁面',3]
['印度飞饼', 22]
['极品木瓜', 666],
['土耳其土豆', 999],
['伊拉克拌面', 1000],
['董卓戏张飞公仔', 2000],
['仿真玩偶', 10000]
]
用户可以反复添加商品,在购物车中记录数量
{'极品木瓜':[个数,单价]}
结算购物车
获取用户购物车中所有的商品计算总价并结算即可
针对添加购物车和结算只有登录的用户才可以执行
解答
# 1.编写一个统计指定文件类型的脚本工具
import os
def count_file(path, suffix):
file_lit = os.listdir(path)
suf_lit = []
for i in file_lit:
if i.split('.')[-1] == suffix:
suf_lit.append(i)
print(len(suf_lit))
if __name__ == '__main__':
path = input('输入路径>>>').strip()
suffix = input('输入文件后缀>>>').strip()
count_file(path, suffix)
# 3.编程小练习
import os
def vim_file(path):
with open(path, 'r', encoding='utf-8') as fr:
print('打开文件:{}'.format(path))
total = fr.readlines()
for i in total:
print(i)
print()
def run():
db_path = os.getcwd()
lit = ['J老师视频合集.txt', 'R老师视频合集.txt', 'C老师视频合集.txt', 'B老师视频合集.txt']
while 1:
for num, i in enumerate(lit):
print('{}.{}'.format(num, i))
n = input('输入要查看文件的编号(q)>>>').strip()
path = os.path.join(db_path, 'db', lit[int(n)])
vim_file(path)
if n == 'q':
print('已退出')
return
if __name__ == '__main__':
run()