IO处理
IO概述
-
文件
文件是一些具有永久存储及特定顺序的字节组成的一个有序的、具有名称的集合。
在各种介质上(可移动磁盘、硬盘、CD、网络 等)存储的集合数据。
通常情况下文件按照树状目录进行组织,每个文件都有文件名、文件所在路径、创建时间、访问权限等属性。 -
那么问题来了:文件在磁盘或其他介质中,而程序在运存中,出现了异质性问题,怎么让不同的介质进行沟通:
I/O:Input/Output
输入和输出都是有参照物的 参照物就是运存即程序
Input就是从其他介质向运存输入,称为“读”(read)介质
Output就是从运存输出到其他介质,称为“写”(write)介质 -
流:
输入和输出是需要“管道”传输的,这个“管道”中流传的是数据,形象化比喻为数据“流”,和我们常识中的水流是相似的 -
异质性问题带了的后续影响:同步和异步
运存的处理速度很快而其他介质处理速度相对较慢
若运存持续等待其他介质完成后才能去做其他事情,就叫同步,但是时间就被白白浪费
若运存不等待,只将数据存入流中,完毕后转做其他事情,其他介质慢慢接收流的数据,称为异步处理,这大大节省了cpu时间,但是异步加重了编程的复杂度
本篇IO编程全部采用同步模式,后续服务端开发再议异步模式!
os文件\目录管理
os模块处理
由于文件在操作系统的资源管理器上,so我们必须借助和操作系统相关的模块:os(operating system)
import os
1辨识操作系统:os.name
print(os.name)
如果是posix,说明系统是Linux、Unix或Mac OS X,如果是nt,就是Windows系统
2环境变量:os.environ
print(os.environ)
3环境变量中某个特定数据:os.environ.get(“key”)
print(os.environ.get(“path”))
4辨识目录权限
os.access(“new_dir”, os.F_OK) # 查看目录是否存在
os.F_OK : 是否存在
os.R_OK : 是否可读
os.W_OK : 是否可写
os.X_OK : 是否可执行
5查看当前目录
print(os.getcwd())
6更改当前目录:程序当次运行中有效
os.chdir("…")
print(os.getcwd())
7创建单级目录:目录若已存在会报异常
if not os.access(“new_dir”, os.F_OK):
os.mkdir(“new_dir”)
8递归创建无限级目录:exist_ok为False若目录存在会报异常 默认False 建议True
os.makedirs(“mydir/sub1/sub2/sub3”, exist_ok=True)
9删除空目录
os.rmdir(“new_dir”)
10递归删除路径上的所有空目录
os.removedirs(“mydir/sub1/sub2/sub3”)
11创建文件
os.open(“1.txt”, os.O_CREAT)
为了防止资源泄露:创建后关闭对文件的连接
os.close(os.open(“1.txt”, os.O_CREAT))
12删除文件 只能删除文件 否则异常
os.remove(“1.txt”)
13重命名文件或目录
os.rename(“1.txt”, “2.txt”)
14重命名文件或目录,可以带全路径一起修正,可以自动递归创建新目录
os.renames(“1.txt”, “aaa/2.txt”)
15显示当前目录下所有的子文件及子目录
print(os.listdir("."))
16显示当前目录中的所有内容(深度遍历)
for root, subs, files in os.walk(".", True):
print(“当前目录”, root)
print(“子目录:”)
for i in subs:
print(root + “\” + i)
print(“子文件:”)
for i in files:
print(root + “\” + i)
os.path模块处理
os.path有四大职责:
1.格式化文件或目录路径
2.文件属性获取
3.辨识路径(存在or不存在、绝对or相对、目录or文件等)
4.解读路径
import os.path
import time
1.格式化文件或目录路径
获取绝对路径
print(os.path.abspath("."))
返回一个路径的当前目录或文件名
print(os.path.basename(r"aaa\2.txt"))
返回一个路径的父目录
print(os.path.dirname(r"aaa\2.txt"))
os.path.join(path1[, path2[, …]]) 把目录和文件名合成一个路径
print(os.path.join(“c:/”, “aaa”, “1.txt”))
规范path字符串形式
print(os.path.normpath(r"./aaa\bbb/ccc\1.txt"))
2.文件属性获取
得到得到文件的大小
print(os.path.getsize(“1.txt”))
返回最近访问时间
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getatime("."))))
返回最近文件修改时间
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getmtime("."))))
返回文件 path 创建时间
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getctime("."))))
3.辨识路径(存在or不存在、绝对or相对、目录or文件等)
判断路径是否存在
print(os.path.exists(r".\5.py"))
判断是否为绝对路径
print(os.path.isabs("."))
判断路径是否为文件
print(os.path.isfile("."))
判断路径是否为目录
print(os.path.isdir("."))
4.拆分路径:获得的是元组
路径拆分为两部分,后一部分总是最后级别的目录或文件名
print(os.path.split(r"aaa\bbb\2.txt"))
路径拆分为两部分,后一部分总是文件的后缀名
print(os.path.splitext(r"aaa\bbb\2.mp4"))
open(…)的file处理
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件 open(文件名,访问模式)
示例如下:
f = open(‘Python.txt’, ‘w’)
close( )
或者:
新建一个文件,文件名为:test.txt
f = open(‘test.txt’, ‘w’)
关闭这个文件
f.close()
with open语句省略关闭
with open(‘test.txt’, ‘w’) as f:
f.read()
文件的open模式 | 备注 |
---|---|
r | 以只读方式打开文件,文件的指针将会放在文件的开头,这是默认模式 |
w | 打开一个文件只用于写入,如果改文件已存在则将其覆盖,如果文件不存在则创建新文件 |
a | 打开一个文件用于追加,如果改文件已存在,文件的指针将会放在文件的结尾,也就是说新的内容将会被写入到已有内容之后,如果该文件不存在,创建新文件进行写入 |
rb | 以二进制格式打开一个文件用于读,文件的指针将会放在文件的开头,这是默认的模式 |
wb | 以二进制格式打开一个文件用于写入,如果文件已存在则将其覆盖,如果文件不存在将其创建 |
ab | 以二进制格式打开一个文件用于追加,如果文件已存在,文件的指针将会放在文件的街结尾,新的内容将会写入到已有内容之后,如果文件不存在,将会常见新文件进行写入 |
r+ | 打开一个文件用于读写,文件指针将会放在文件的开头 |
w+ | 打开一个文件用于读写,如果该文件已存在将其覆盖,如果文件不存,在将其创建 |
a+ | 打开一个文件用于读写,如果文件已存在,文件的指针将会放在文件的结尾,文件打开时会是追加模式,如果文件不存在,创建新文件用于读写 |
rb+ | 以二进制格式打开一个文件用于读写,文件的指针将会放在文件的开头 |
wb+ | 以二进制格式打开一个文件用于读写,如果文件已存在将其覆盖,如果文件不存在,创建新文件 |
ab+ | 以二进制格式打开一个文件用于追加,如果文件已存在,文件指针将会放在文件的结尾,如果文件不存在,创建新文件用于读写 |
读取文件
使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
f = open('python.txt', 'r')
content = f.read(5)
print(content)
print("-"*30)
content = f.read()
print(content)
f.close()
注意:如果open是只读打开一个文件,那么可以不用写打开的模式,
即只写 open(‘python.txt’)
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
f = open('python.txt', 'r')
content = f.readlines()
print(type(content))
i=1
for temp in content:
print(i, temp)
i+=1
f.close()
f = open('python.txt', 'r')
content = f.readline()
print("1:", content)
content = f.readline()
print("2:", content)
f.close()
写入文件
写数据(write)
使用write()/writelines可以完成向文件写入数据
f = open('Test.txt', 'w')
f.write('hello world, i am here!')
f.close()
注意:如果文件不存在那么创建,如果存在那么就先清空,然后写入数据
读写文件
复制文件:
import os
#原始路径,目标路径
def Copy_Files(oriPath,endPath):
#判断路径是否存在
endPathDir=os.path.dirname(endPath)
if not os.path.exists(endPathDir):
os.makedirs(endPathDir)
#读取数据并写入数据
with open(oriPath,"rb") as fr:
r=fr.read()
with open(endPath,"wb") as fw:
fw.write(r)
序列化和反序列化
- Python序列化和反序列化
通过将对象序列化可以将其存储在变量或者文件中,可以保存当时对象的状态,实现其生命周期的延长。并且需要时可以再次将这个对象读取出来。
Python中有几个常用模块可实现这一功能。
pickle
内存上的序列化:
import pickle
#字典序列化
dic = {'age': 23, 'job': 'student'}
byte_data = pickle.dumps(dic)
# out -> b'\x80\x03}q\x00(X\x03\x00\x00\...'
print(byte_data)
#字典反序列化
obj = pickle.loads(byte_data)
print(obj)
借助文件的序列化:
# 序列化
with open('abc.txt', 'wb') as f:
dic = {'age': 23, 'job': 'student'}
pickle.dump(dic, f)
# 反序列化
with open('abc.txt', 'rb') as f:
aa = pickle.load(f)
print(aa)
print(type(aa)) # <class 'dict'>
json
- pickle可以很方便地序列化所有对象。不过json作为更为标准的格式,具有更好的可读性(pickle是二进制数据)和跨平台性。是个不错的选择。
json使用的四个函数名和pickle一致。
内存中的序列化:
import json
dic = {'age': 23, 'job': 'student'}
dic_str = json.dumps(dic)
print(type(dic_str), dic_str)
# out: <class 'str'> {"age": 23, "job": "student"}
dic_obj = json.loads(dic_str)
print(type(dic_obj), dic_obj)
# out: <class 'dict'> {'age': 23, 'job': 'student'}
json文件的序列化:
import json
dic = {'age': 23, 'job': 'student'}
with open('abc.json', 'w', encoding='utf-8') as f:
json.dump(dic, f)
with open('abc.json', encoding='utf-8') as f:
obj = json.load(f)
print(obj)