08 文件IO os.path pathlib.Path shutil模块 csv ini 序列化 正则表达式

1 篇文章 0 订阅
1 篇文章 0 订阅

文件IO

  • IO是输入输出的简称
  • 输入设备将数据或程序输入到计算机
    • 键盘 鼠标 等
  • 输出设备将数据或程序的处理结果展示给用户
    • 显示器 打印机
  • 文件IO常用操作
itemitem
open打开
read读取
write写入
close关闭
readline行读取
readlines多行读取
seek文件指针操作
tell指针位置
打开操作
  • open(file:str, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) 常用参数为前四个
    1. file 指定文件目录 只写文件表示与py文件同目录 为防止使用\出错 可写成r”C:\Users\6k\sample.txt”形式
    2. mode rwa 分别表示只读 只写 追加 默认为t文本模式 加b表示二进制模式
    3. buffer为缓冲 是为解决从内存写入到硬盘的速度太慢而设置的临时存储区域
    4. encoding 表示设置被打开文件的编码 默认为当前系统编码 简体中文版Windows为 GBK 在python里称作cp936
    5. 打开最后一定记得要关闭文件
字符解释错误操作存在-创建-策略
r缺省设置,只读打开write文件不存在则抛FileNotFoundError异常
t缺省设置,文本模式
w只写打开read文件不存在则创建 存在则先清空内容
x创建并只写新文件read不存在则创建 存在则抛FileExistsError异常
a只写打开,文件存在则追加read文件不存在则创建 内容追加
b二进制模式
+加在rw之后,添加写入和读取功能

总结:
- r为只读 wxa均为只写
- wxa都可产生新文件
- w 无论文件存在与否 都会生成全新内容的文件
- a 无论文件存在与否 都会在文件尾部追加内容
- x 必须要求文件事先不存在 再创建新文件
- 文本模式t 字符流 按某种字符编码理解 操作字符
- 二进制模式b 字节流 与字符编码无关 操作字节

文件指针
  • mode=r 指针在0
  • mode=a 指针在EOF 文件末尾
  • tell() 显示当前指针位置
  • seek(offset[,whence])
    • 文本模式下
    • whence默认为0 表示从头开始 offset只能取正整数
    • whence=1 表示从当前位置开始 offset只能取0 原地不动
    • whence=2 表示从EOF开始 offset只能取0 可从任意位置移至EOF
    • seek按照字节偏移
    • 二进制模式下
    • whence默认为0 表示从头开始 offset只能取正整数
    • whence=1 表示从当前位置开始 offset可正可负
    • whence=2 表示从EOF开始 offset可正可负
    • 二进制模式支持任意位置偏移.向后可超界,向前不能超界.
  • seek(0) 等价于 seek(0,0) 表示将指针移至开头
buffering 缓冲区
  • 缓存区是内存中的一段空间 一般来说是一个先进先出(FIFO)的队列,若缓冲区满了或达到阈值,数据会flush(写入)到硬盘
  • f.close()命令会调用flush()
  • buffering = -1 表示使用缺省大小的缓冲
    • 二进制模式 使用io.DEFAULT_BUFFER_SIZE设定buffer大小 默认为8192
    • 文本模式下 终端设备为行缓存模式 其他设备为二进制缓冲策略
  • buffering = 0 只在二进制模式使用 表示关闭buffer
  • buffering = 1 表示只在文本模式使用 为行缓冲模式 见到换行符就flush
  • buffering = int(大于1) 表示使用指定大小的缓冲
  • buffer总结
    • 文本模式,一般用默认缓冲大小
    • 二进制模式是一个个字节的操作,可指定buffer大小
    • 一般来说 默认缓冲大小已经是最优选择 除非明确知道 否则不要调整
    • 一般情况 若明确知道要写入磁盘 可以手动flush
encoding
  • None表示默认编码 依赖操作系统 简体中文版windows下默认为GBK Linux下默认为UTF-8
其他参数
  • error 编码容错
    • None和strict 有编码错误就抛异常
    • ignore表示忽略
  • newline 文本模式换行符的转换
itemsNone指定合法字符
‘\r’ ‘\n’ ‘\r\n’都被转化为’\n’不自动转化通用换行符指定字符换行
‘\n’转化为系统缺省行分隔符os.linesep”或’\n’表示不替换‘\n’被替换为指定字符
closefd
  • 关闭文件描述符 True表示关闭 False会在文件关闭后保持这个描述符
  • 可用fileobj.fileno()查看
read(int)
  • 读取指定数量的字符或字节
  • int 取负数或None表示读取到EOF
行读取
  • readline(size=-1)
    • 一行行读取 size设置读取的字符或字节数
  • readlines(hint=-1)
    • 读取所有行的列表 指定hint则返回指定的行数
write
  • write(s) 把字符串s写入文件并返回字符个数
  • writelines(lines) 将字符串列表写入文件

上下文管理

  • Linux系统对文件打开数量做了限制
  • lsof -p 进程号| grep test | wc -l 可查看文件被同时打开了几次
  • ulimit -a 查看所有限制 openfile为打开文件数的限制 默认为1024
  • 此异常因系统资源限制产生 但不易察觉 很多时候表现为OSError
  • 因此打开的文件 用完后一定要关闭
  • 为解决此类问题 引出上下文管理
    • 使用with … as 关键字
    • 上下午管理的语句块不会开辟新的作用域
    • with语句块执行完毕会自动关闭文件对象
with open('test') as f:
    print(f.read())
  • 文件IO类的对象 不使用时都应及时关闭以释放资源
  • IO被打开就会获得文件描述符. 计算机资源有限,操作系统会做限制.
  • 除非明确知道资源情况,否则不建议提高资源限制值.

StringIO BytesIO

  • io模块里的类 from io import StringIO
  • StringIO在内存中开辟的文本模式buffer 可像文件对象一样被操作
  • BytesIO在内存中开辟二进制模式buffer
  • 调用close方法 此buffer会释放
  • getvalue()可获取全部内容 不受指针位置影响
from io import StringIO
sio=StringIO()
sio.write('Python2018')
sio.seek(0)
sio.read()
sio.getvalue()
sio.close()
  • 磁盘操作比内存操作慢得多 在内存充足的情况下 应减少数据落地 减少磁盘IO 可大大提高程序的运行效率

类文件对象 file-like-obj

  • 可像文件对象一样操作
  • socket对象 输入输出(stdin stdout)对象都是类文件对象

目录相关操作

  • python3.4之前 多使用os.path模块
from os import path
p=path.join('/etc','sysconfig','network')  --> '/etc\\sysconfig\\network':str
sp=path.split(p) --> ('/etc\\sysconfig', 'network'):tuple
path.exists(p) --> False
path.abspath('.') --> 'C:\\Users\\6k':str
  • python3.4以后 建议使用pathlib模块,提供Path对象来操作.包括目录和文件.
  • 初始化
from pathlib import Path
p=Path() #p为Path对象
p=Path('a','b','c/d')
p=Path('/etc')
  • 操作符/
    • Path对象/Path对象
    • Path对象/字符串
    • 字符串/Path对象
  • joinpath(*other) 连接多个字符串到Path对象
p=Path()
p1=p/'a'
p2='b'/p
p3=Path('c')
p4=p1/p2/p3
p4.parts --> ('a', 'b', 'c'):tuple
p4.joinpath('/*',p3,p2) --> '/*/c/b' #p4不变
#p是Path对象 可用str和bytes转化
  • 目录相关属性
属性解释
parent逻辑父目录
parents父目录序列(生成器) 索引0是直接父目录
suffix目录最后一部分的扩展名
stem目录最后一部分 无扩展名
suffixs多个扩展名列表
with_suffix(suffix)补充扩展名至尾部 返回新路径 扩展名存在则无效
with_name(name)替换目录最后一部分并返回新路径
cwd()返回当前工作目录
home()返回家目录
is_dir() file symlink socket block_devices char_devices absolute是否是对应文件/设备 返回布尔值
absolute()返回绝对路径
resolve()返回绝对路径 软链接则返回真实路径
exists()目录或文件是否存在
rmdir()删除空目录 未提供判断目录为空的方法
mkdir(mode=0o777,parents=False,exist_ok=False)parents:是否创建父目录 选True表示mkdir -p ; exist_ok:选True忽略FileExistsError错误
touch(mode=0o666,exist_ok=True)创建文件
as_uri()将路径转化为URI
iterdir()迭代当前目录(生成器)
通配符
  • 返回生成器
  • glob(pattern) 通配给定的模式
  • rglob(pattern) 通配给定的目录 递归访问目录
  • list(p.glob(‘*/.py’)) 等价于list(p.rglob(‘*.py’))
  • match(pattern) 匹配模式 匹配成功返回True
Path('a/b.py').match('*.py')
Out[172]: True
Path('a/b/c.py').match('b/*.py')
Out[173]: True

Path('a/b/c.py').match('a/*.py')
Out[174]: False

Path('a/b/c.py').match('a/**.py')
Out[175]: False

Path('a/b/c.py').match('a/**/*.py')
Out[176]: True

Path('a/b/c.py').match('**/*.py')
Out[177]: True
  • stat() 等同于stat命令 用于查看文件状态
  • lstat() 同stat() 若为符号链接 则显示链接本身的文件信息
  • read_text() 调用open 以rt方式读取对应文件 返回文本
  • write_text() 调用open 以wt方式写入对应文件 返回文本
  • 类似属性还有bytes
OS/Platform
property/methodresult
os.namewindows是nt linux是posix
os.uname()*nix支持 查看内核信息
sys.platformwindows是win32 linux是linux
os.listdir(path:str)返回目录内容列表
os.stat(path)调用linux系统stat
os.chmod(path,mode,*,dir_fd=None,follow_symlinks=True)os.chmod(‘test’,0o777) 需要有相应权限
os.chown(path,uid,gid)改变文件属主属组 需要有相应权限

shutil模块 (高级文件操作)

  • copyfileobj(fsrc,fdst[,length])
    • 文件对象的复制 fdst要求可写 length用于指定buffer
  • copyfile(src,dst,*,follow_symlinks=True)
    • 复制文件内容 不含元数据 本质上调用copyfileobj
  • copymode(src,dst,*,follow_symlinks=True)
    • 仅复制权限
  • copystat(src,dst,*,follow_symlinks=True)
    • 复制元数据 权限只是元数据的一部分
  • copy(src,dst,*,follow_symlinks=True)
    • 复制内容 权限及部分元数据 不包含创建时间与修改时间
      本质上调用的是copyfile 与copymode
    • copy2 可复制所有元数据 需平台支持 调用copyfile与copystat
  • copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False)
    • 递归复制目录 默认使用copy2
    • src dst 必须是目录 前者必须存在 后者相反
    • ignore=func 提供callable(src,name) -> ignored_names:set src为源目录 names是os.listdir(src)的结果 返回值为要被过滤掉的文件名的集合
    • ignore函数示例
def ignore(src,names):
    ig=filter(lambda(x:x.startwith('a'),names)
    return set(ig)
  • rmtree(path, ignore_errors=False, οnerrοr=None)
    • 递归删除 如同 rm -rf 慎用
    • 不是原子操作 有可能删除错误 当ignore_errors为False或omitted时生效
    • onerror为callable 接受函数function path和exeinfo
  • move(src, dst, copy_function=copy2)
    • 递归移动文件和目录到目标 返回目标
    • 本身使用os.rename或copytree
csv文件
  • csv
    • 带有行和列的文本文件
    • 行分隔符\r\n,末行可省略
    • 列分隔符常为逗号或制表符
    • 每一行称为一条记录 record
    • 为显示以上分隔符,需用双引号
    • 两个双引号表示转义
from pathlib import Path
p=Path('d:/py/charm/test.csv')
parent=p.parent
if not p.exists():
    parents.mkdir(parents=True)
body='''\
id,name,age,comment
1,zs,18,"i'm 18"
2,ls,20,"this is a""test"" string"
3,ww,23,"中文行换


测试"
'''
p.write_text(body)
  • csv模块
  • reader(csvfile,dialect=’excel’,**fmtparams)
  • 返回DictReader对象 是一个行迭代器
  • writer(csvfile,dialect=’excel’,**fmtparams)
import csv,pathlib
p=pathlib.Path('d:/pycharm/test.csv')
with open(str(p)) as f:
    reader=csv.reader(f)
    print(next(reader))
    print(next(reader))
rows=([1,2,3,4],('a','b','c','d'),range(11,15),'efgh',((20,),(50,)))
row=rows[0]
with open(str(p),'a',newline='') as f:
    writer=csv.writer(f)
    writer.writerow(row)
    writer.writerows(rows)

这里写图片描述

  • ini最早问为初始化文件,后演变为配置文件
  • 内容如下
[DEFAULT]
a = test
[mysql]
default-character-set=utf8
a = 1000
[mysqld]
datadir =/dbserver/data
port = 33060
character-set-server=utf8
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
  • 中括号内部分称作section ,译作节 区 段
  • section内为key=value形式的键值对,key称作option(选项)
  • DEFAULT为缺省section名称 必须大写

  • configparser模块的ConfigParser类可用于操作ini文件

  • 常用操作如下:
from configparser import ConfigParser
cfg = ConfigParser()
cfg.read(r"D:\Pycharm\test.ini")
print(cfg.sections(),'\n') #不显示DEFAULT
for k,_ in cfg.items():
    print(k,cfg.items(k),'--------------',sep='\n')
tmp=cfg.get('mysqld', 'port')
print(tmp,type(tmp))
if not cfg.has_section('test'):
    cfg.add_section('test')
#多种赋值方式
cfg.set('test', 'tom','1')
cfg['test']['jerry'] = '2'
cfg['test']={'1':'500','tom':'cat','jerry':'mice'}#覆盖原有内容
print(cfg.getint('test','tom'))#写入文件
with open(r"D:\Pycharm\new_test.ini",'a') as f:
    cfg.write(f)

序列化与反序列化

  • 序列化serialization:将内存中的对象转化为一个个字节 (反之则叫反序列化)
  • 持久化(persistence) :数据序列化后保存到文件
pickle库:Python的序列化与反序列化模块
Created with Raphaël 2.1.2 字节对象 字节对象 内存对象 内存对象 文件对象 文件对象 loads Dumps Dump load
  • 上面提到的dump(s)与load(s)是序列化里的通用概念
  • dump(s)与序列化对应,指从内存导出
  • load(s)与反序列化对应,指载入内存
  • 不加s的方式,数据存入磁盘,需要数据落地.应尽量避免
  • 加s的方式,数据不落地,一般通过网络传输
import pickle
n='pickle'
d={'a':1,'b':'asd','c':[1,2,3]}
l=list('123')
i=99
with open(n,'wb') as f:
    pickle.dump(d,f)
    pickle.dump(l,f)
    pickle.dump(i,f)
with open(n,'rb') as f:
    print(f.read(),f.seek(0))
    for _ in range(3):
        x= pickle.load(f)
        print(x,type(x))

class AAA:
    def __init__(self):
        self.tttt='abc'
    def show(self):
        print('xyz')

aaa=AAA()         
sr=pickle.dumps(aaa)
print(sr)
with open('pickle_obj','wb') as f:
    pickle.dump(aaa,f)
with open ('pickle_obj','rb') as f:
    new_aaa=pickle.load(f)
    new_aaa.show()
  • 序列化后的用途
    • 持久化(应用较少)
    • 网络传输,收发双方需用相同的环境(自定义类双方都要定义)
    • pickle只能保证在python语言之间传输
  • 跨平台 跨语言的公共协议 : XML JSON Protocol_Buffer
JSON
  • 轻量级数据交换格式.用文本格式存储与表示数据
  • 本质上说,JSON是文本字符串
  • 独立于编程语言,几乎所有编程语言都支持
  • python JSON模块
    • JSON数据很少落地.一般都通过网络传输,此时需考虑压缩
import json
d={1:'s','name':'tom','EDM':['house','psy']}
j=json.dumps(d)
print(j,type(j))#注意数据类型以及引号的变化
new_d=json.loads(j)
print(new_d,type(new_d))
  • python MessagePack模块
    这里写图片描述
    • 基于二进制的高效的对象序列化库
    • 比JSON更轻巧 更快速
    • 安装命令 : ‘pip install msgpack-python’
    • 导入方式 : import msgpack
    • 兼容JSON与pickle,用法与前两者一致

正则表达式 Regular Expression

  • 文本处理工具
  • 元字符 metecharacter
代码说明举例
.匹配除换行符外任意一个字符
[abc]匹配中括号内任意一个字符,多选一
[^abc]匹配除去中括号内字符的任一字符
[a-z]匹配任一小写字母
[^a-z]匹配任一非小写字母
\b匹配单词边界\bc匹配c开头的单词 d\b匹配d结尾的单词
\B对应小写字母取反\Bc匹配含有c且不以c开头的单词
\d等价于[0-9]
\D等价于[^0-9]
\s匹配任一空白字符(换行符 制表符 空格) 等价于[\f\r\n\t\v]
\S等价于[^\f\r\n\t\v]
\w等价于[a-zA-Z0-9_],包括中文
\W等价于[^a-zA-Z0-9_]
  • 重复
代码说明
{n}前面的表达式重复n次
{n,}前面的表达式至少重复n次
{n,m}前面的表达式重复n到m次
?前面的表达式重复0次或1次
*等价于{0,}
+等价于{1,}
  • 贪婪模式
    • 正则表达式默认为贪婪模式,会尽量匹配长的字符
    • 在重复符号后加?则改为非贪婪模式
    • 例如 {n,m}? 或 *?
  • 分组(捕获)
代码说明举例
x|y匹配x或y
(pattern)小括号表示分组,分组号从1开始
\分组号匹配对应分组号的分组
(?:pattern)只用小括号表示改变优先级,不设置分组industr(?:y|ies)等价于industry|industries
(?exp)分组自命名Python语法为(?Pexp)
  • 断言
    • 相当于将exp作为条件判断
    • 只匹配pattern的内容
    • 不占用分组号
代码说明举例
pattern(?=exp)断言pattern右边一定出现expf(?=oo) : f后面一定有oo
(?<=exp)pattern断言pattern左边一定出现exp(?<=oo)f : f前面一定有oo
pattern(?!exp)断言pattern右边一定不出现expf(?!oo) : f后面一定没有oo
(?断言pattern左边一定不出现exp(?
  • RE引擎选择
代码说明举例
IgnoreCase匹配时忽略大小写re.I re.IGNORECASE
Singleline单行模式(把所有文本当做一行)re.S re.DOTALL
Multiline多行模式(^行首 $行尾)re.M re.MULTILINE
IgnorePatternWhitespace忽略表达式中的空白字符,使用空白字符需转义re.X re.VERBOSE
  • 正则表达式例子
  • 手机号
    • 1[3-8]\d{9}
  • 0~999之间的数字
    • \b(?:[1-9]\d\d?|\d)\b
  • IP地址
    • (\d{1,3}\.){3}(\d{1,3})
    • 0~255的范围问题交给socket模块处理更合适
import socket
ipaddr=socket.inet_aton('192.168.1.001')
  • 带有ftp的链接,且文件类型是gz或xz
    • .*ftp.*.(?:gz|xz)
Python re模块
  • 编译
    • re.compline(pattern,flags) -> regex_obj
    • 编译后下次用相同的pattern时不再编译.可提高效率
    • flags用于指定编译引擎
  • 单次匹配
    • 从指定位置开始,找到第一个就停下来
import re
re.match(pattern, string, flags=0)#不编译使用,不推荐
regex=re.compline(pattern,flags) -> regex_obj
regex.match(string, pos=0, endpos, pattern=None)
regex.search(string, pos=0, endpos, pattern=None)
regex.fullmatch(string, pos=0, endpos, pattern=None)
  • 全文搜索
    • 寻找所有匹配项,返回一个容器
regex.findall(string, pos=0, endpos, pattern=None) -> list#返回所有匹配项的列表
regex.findall(string, pos=0, endpos, pattern=None) -> iterator#返回由匹配项组成的迭代器,每次迭代返回match对象
  • 匹配替换
    • 对pattern匹配到的字符串用repl替换 repl可以是str bytes function
reg.sub(repl, string, count=0)
reg.subn(repl, string, count=0)#同sub 返回元组(new_string, number_of_subs_made)
  • 字符串分割
    • 用pattern对字符串进行分割
import re
s='''01 bottle
02 bag
03      big1
100         able'''
reg=re.compile('[\s\d]+')
reg.split(s) --> ['', 'bottle', 'bag', 'big', 'able']
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值