csv 和ini文件处理

作者: 一个小菜鸡

csv常见格式

nums     options      arguments

逗号分割值 comma-Separated Values

CSV是一个被行分隔符,列分隔符划分成行和列的文本文件

reader(csvfile,dialect = 'excel' ,**fmtparams)

返回DictReader的实例,是行迭代器

delimiter 列分隔符,逗号

quotechar 字段的引用符号,缺省为“ ,双引号

双引号的处理:

doubleqipte双引号的处理,默认为True。如果和quotechar为同一个,True则使用2个双引号表示

False表示使用转义字符将作为双引号的浅醉

escapechar 一个转义字符,默认为None

quoting 指定双引号的规则

writer( csvfile,dialect='excel',**fmtparams)

返回DictWriter的实例

主要方法有writerow , writerows

当文档中有引号的语句对象时,可在 语句外再添加一对引号以示区分

ini文件的读解:

ini文件中,中括号里面的称为section

每一个section内,都是 key=value 形成的键值对,key称为option选项

ini文件使用configparser来进行解析

configparser模块的ConfigParser类就是用来操作

read(filenames,encoding=None)

读取ini文件,可以是单个文件,或者是文件列表,可以指定文件编码(utf-8?)

sections()返回section列表,缺省section不包括在内

add_section(section_name)增加一个section

has_section(section_name)判断section是否存在

options(section)返回section的所有option

has_option(section,option)判断section是否存在这个option

get(section,option,*,raw=False,vars=None[fallback])

从指定段的选项上取值,如果找到就返回,没找到就去default寻找默认值

items(section,raw = False,vars=None)

没有section,则返回所有section名字及其对象,如果指定section,则返回这section的键值对组成的二元组

set(section,option,value)

section存在的情况下,写入option=value,要求option,value必须是字符串

remove_section(section)

移除section及其所有option

remove_optioon(section,option)

移除section下的option

write(fileobject,space_around_delimiters=True)

将当前config的所有内容写入fileobject,一般open函数使用w模式

shutil 模块使用

作者: 一个小菜鸡

shutil 高级文件操作

提供关于文件的复制和删除

在执行复制操作时,不能完全的拷贝文件和数据,所以有可能会造成数据缺失,以及权限无法复制的缺陷

在导入了shutil模块后,可以使用以下命令:

copyfileobj(fsrc,fdst [length])          (元文件,拷贝对象,【缓存长度限制】)

文件对象的复制, fsrc 和 fdst 是open打开的文件对象,复制内容,fdst 要求可写

length指定了 buffer 的大小

使用copyfileobj 时应注意 指针问题,应为w新建一个不存在的文件时,所写入的文件内容均在尾端,所以直接拷贝过去的内容为空,应将指针归0再进行拷贝

copyfile( src , dst )

实际上底层实现的也是copyfileobj函数调用,可以复制文件内容,不含元数据,二进制内容复制

copymode( src , dst ),只复制权限

copystat( src , dst ) 复制元数据,stat 包含权限

copy( src dst) 复制文件内容,权限和部分元数据,不包括创建时间和修改时间 :本质上调用了 copyfile 和copystat

copy2(src,dst)比copy多了复制全部元数据,但需要平台

本质上调用的是: copyfile copystat

copytree( src dst ) 递归的复制目录,默认使用copy2,也就是带更多的元数据复制

使用前提  src必须存在,dst必须不存在

copy时过滤掉某些不需要拷贝的文件,可使用copy( ignore=??? )参数来过滤掉不需拷贝的文件

rm删除

shuti.rmtree(path.......)

递归删除吗,和rm-rf一样,慎用,它不是原子操作,有可能删除错误,删除的就删除了

move移动

move(src dst,copy_function=copy2)

递归移动文件,目录到目标,返回目标

本身使用的是 os.rename方法

如果不支持rename,如果是目录则想copytree再删除源目录

默认使用copy2方法

shutil还有打包功能,生成tar并压缩,支持zip,gz,bz,xz格式

思考:

为什么要使用序列化?

使用序列化之后,就可以将序列化后的内容写入磁盘,或者通过网络传输到别的机器上

为什么要使用反序列化?

一个文件序列化之后是不方便使用者对其进行查看或者修改的,所以使用反序列化,可以还原他未序列化时的文件模型

将变量内容从序列化的对象重新读取到内存里称之为反序列化

pickle使用时需要注意,发送和接收方的pickle版本可能不一致,从而导致序列化的出来的文件也不一致

使用pickle操作时,用什么方法写入,就必须用什么方法读取(dump,load)(dumps,loads)

pickle库

dumps 对象序列化

dump 对象序列化到文件对象(存入文件)

loads 对象反序列化

load 对象反序列化,从文件中读取数据

使用模块pickle对一个文件或者数据类型进行序列化:

举例:

import pickle

d = dict(name = Bob , age = 20 , Score =88)

pickle.dumps(d)

返回结果为:

b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'

pickle.dumps()方法把任意序列对象序列化为一个bytes,然后可以将这个bytes写入文件,或者

举例:

with open( 'I:/readme.txt', 'wb' )as f :

pickle.dump(需要保存的数据或文件,被保存的实体对象)

pickle.dump(d , f)

用pickle.dump()直接把一个对象序列化后写入一个类文件对象中!

查看写入硬盘的文件,是一对二进制数据,不便于查看,这就是python序列化后的内部信息

当我们要把对象从磁盘读到内存中时,可以先把内容读到一个bytes中,再用pickle.loads()反序列化出对象,也可以使用pickle.load()方法从一个类文件对象中,直接反序列化出对象

举例:

with open('I:/readme.txt', 'rb' ) as f :
pickle.load( f )
print(f)

会显示:

{'age': 20, 'score': 88, 'name': 'Bob'}

这个变量和原来的变量是完全不相干的对象,只是他们的内容相同而已

pickle的问题和其他编程语言特有的序列化问题一样,只能用于python中,不能跨语言,版本使用,所以只能用pickle保存一些补重要的数据,即便不能成功的反序列化也没有关系

可调式性/可读性

可调试性/可读性

序列化和反序列化的数据正确性和业务正确性的调试往往需要很长的时间,良好的调试机制会大大提高开发效率。序列化后的二进制串往往不具备人眼可读性,为了验证序列化结果的正确性,写入方不得同时撰写反序列化程序,或提供一个查询平台--这比较费时;另一方面,如果读取方未能成功实现反序列化,这将给问题查找带来了很大的挑战--难以定位是由于自身的反序列化程序的bug所导致还是由于写入方序列化后的错误数据所导致。对于跨公司间的调试,由于以下原因,问题会显得更严重。

支持不到位,跨公司调试在问题出现后可能得不到及时的支持,这大大延长了调试周期。

访问限制,调试阶段的查询平台未必对外公开,这增加了读取方的验证难度。

如果序列化后的数据人眼可读,这将大大提高调试效率, XML和JSON就具有人眼可读的优点。

Json

js对象标记,是一种基于ECMAscript的一个子集,采用完全独立于编程语言的文本格式来村粗和表示数据的一种轻量化级的数据交换格式

jason的数据类型

值: 双引号引起来的字符串,数值,true和fales,null,对象,数组,这些都是值


字符串: 由双引号包围起来的任意字符的组合,可以有转义字符

数值: 有正负,有整数,浮点数

对象: 无序键值对的集合{k,v.......k,v},key必须是一个字符串,value可以是任意的值


数组:

有序的值的集合

格式[val1......valn]


json模块

python至此少量内建数据类型到json类型的转换


常用方法:

dumps json 编码

dupm json 编码并存入文件

loads json     解码

load json     解码,从文件中读取数据

jason编码的数据很少落地,数据都是通过网络传输, 传输的时候,要考虑压缩

本质上来说他就是个文本,是一个字符串,所以他的应用范围及其广泛

MessagepackPack

基于二进制搞笑的对象序列化类库,可用于跨语言通信

兼容json和pickle,比json更快速,更轻巧

原理:将一些可以替代的变量名,用ascii码来替代,从而大大的减少空间占用

安装:

使用pip安装:

pip install msgpack-python

使用方法:

packb 序列化对象,提供了dumps 来兼容json和pickle

unpackb 反序列化对象,提供了loads来兼容json和pickle

pack序列化对象并保存到文件对象,提供了dump来兼容

unpack 反序列化对象保存到文件对象,提供了load来兼容

MessgePack简单易用,且高效压缩,支持的语言也很多,也是一种序列化可选的方法

文件操作

作者: 一个小菜鸡

读取txt文件并进行切割

f = open(b'sample.txt','r+',encoding='utf-8')
alpha = f.read().split(' ')
dic = { }
for k,v in enumerate(alpha):
if v in dic:
countine
else:
dic[k]=v
print(len(dic))          待续(符号没有切)

文件io常用操作:

open     打开

read      读取     read(size=-1) size表示读取多少个字符或字节,负数或者None表示读取到EOF(末尾)

write     写入     write(s),把字符串s写入到文件中,并返回字符的个数

close     关闭     flush并关闭文件对象,文件已经关闭,再次关闭没有任何效果

readline     按行读取     read(size=-1) 一行行读取文件内容,size设置一次能读取行内几个字符或字节

readlines     多行读取(hint=-1) 读取所有行的列表,指定hint则返回指定的行数

seek     文件指针操作

tell       查看当前指针位置

其他:

seekable()是否可seek

readable()是否可读

writable()是否可写

closed是否已经关闭

文件查看格式:

open(filename,buffering=1,encoding=None,errors=None,newline=None,closefd=True)

打开一个文件对象(流对象)和文件描述符,打开文件失败,则返回异常

一般文件使用方法:

f = open('test')   #打开文件(可以跟上 相关操作)
windows :io.TextIOWrapper name='test' mode='r' encoding='cp936'
linux:       io.TexrTOWrapper name='test' mode='r' encoding='utf-8'
print(f.read())     #读取文件
f.close()             # 关闭文件

文件操作中最常用的就是读和写

文件访问的模式有两种:文本模式和二进制模式,不同模式下,操作函数不尽相同,表现的结果也不一样

open的参数

指定一个文件文明,如果不指定路径,默认是当前路径

mode模式:

open(filename,' r ')

不带参数默认只读打开

r模式 只读(不可写,文件不存在会抛出异常)

w模式 只写(不可读,文件存在清空内容,不存在新建文件)

x模式 文件不存在,创建文件,并只写方式打开,文件存在,抛异常

a模式,只写打开,文件存在,默认在末尾追加,文件不存在,新建后只写打开,追加内容

r只读,wxa都是只写

wxa都可以产生新的文件,w不管文件在与否,都会审计过程全新内容的文件, a不管文件是否存在都能在打开的文件尾部追加,x必须要求文件事先不存在,自己造一个新文件

文本模式t

字符流,将文件的字节按照某种字符编码理解,按照字符操作,open的默认mode就是rt

二进制模式b

字节流,将文件就按照字节理解,与字符编码无关,二进制模式时,字节操作使用bytes类型

+

为r w a x 提供缺失的读写功能,但是获取文件对象依旧按照r w a x 自己的特征

+ 不能单独使用,可以认为他是为前面的模式字符做增强的功能

文件指针

文件指针,只想当前字节位置

当mode=r 时,指针起始在0

当mode = a时,指针在eof尾部

tell()      显示当前指针所在位置

seek( offset, [起点] )

移动文件指针位置,offset便宜多少字节,起点从哪里开始

文本模式下:

起点0 缺省值,表示从头开始offset只能正整数

起点1 表示从当前位置开始,offset只接受0

起点2 表示从末尾(EOF)开始,offset 只接受0

文本模式支持从开头向后便宜的方式

二进制模式下

起点0 表示从头开始,offset只能时正整数

起点1 表示从当前位置,offset可正可负

起点2 表示从EOF开始,offset可正可负

二进制模式支持任意起点的偏移,从头,尾中间位置开始

向后seek可以超界,但是向前seek的时候,不能超届,否则异常

buffering:缓冲区

-1 表示使缺省值大小的buffer,如果是而精致模式,使用io.defaults_buffer_size值,默认是4096或者8192

如果是文本模式,如果是终端设备,是行缓存方式,如果不是则使用二进制的策略

:0只在二进制模式使用,表示管buffer

1只在文本模式使用,表示使用行缓冲,意思就是见到换行符flush

大于1 用于指定buffer的大小

flush()将缓冲区数据写入磁盘

close( )关闭前会调用flush()

文本模式一般都是用默认缓冲区大小

二进制模式,是一个个字节的操作,所以指定buffer的大小

一般来说默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整它

一般编程中,明确知道要写入磁盘,就手动调用依次flush,而不是等到它自动flush或者在close的时候

上下文管理:

ulimit -a查看所有限制,其中open files就是打开文件数的限制,默认1024

异常处理:

当出现异常的时候,拦截异常,但是因为很多代码都可能出现oserror异常,不好判断异常,是因为资源限制产生的

f = open('test')
try:
f.write('abc')     #文件只读,写入失败
finally:
f.close()     #正确做法

使用finally可以保证打开的文件可以被关闭

上下文管理,一种特殊的语法,交给解释器取释放文件对象

使用with...as关键字

上下文管理的语句块并不会开启新的作用域

with语句块执行完的时候,会自动关闭文件对象

def f
with open('test')as f:
f.write('hello')     #文件只读,写入失败

f.closed(测试f是否关闭)

上下文管理:

使用with...as 关键字

上下文管理的语句块并不会开启新的作用域

with语句块执行完的时候,会自动关闭文件对象

路径操作

作者: 一个小菜鸡

3.4以前的版本:

使用 os.path模块

from os import path

创建一个路径对象

p = path.join('/etc','sysconfig','network')

使用pash.split(p) 来切出大多数文件路径末尾的文件

将文件路径字符串化,使用 path.dirname(字符串路径赋值的变量 )就可以轻松的取出他的文件路径

将文件路径字符串化,使用 path.basename(字符串路径赋值的变量 )就可以轻松的取出他的基名

将文件路径字符串化,使用 path.splitdrive(字符串路径赋值的变量)就可以轻松的取出它所在的磁盘

3.4以后版本使用

pathlib模块,提供path对象来操作,包括目录和文件

from pathlib import Path               #P为大写

目录操作

初始化目录

p=Path( )     #当前目录
p=Path('a','b','c/d')     #当前目录下的a/b/c/d
p=Path('/etc')      #根下的etc目录

路径的拼接和分解

操作符:

Path对象/Path对象

Path对象/字符串  or  字符串/Path对象

分解parts属性,返回路径中的每一个部分

joinpath(*other) 连接多个字符串到Path对象中

获取路径

p=Path('/etc')

str 获取路径字符串,bytes获取路径字符串的bytes

p = Path(str(p),bytes(p))

父目录:

parent目录的逻辑父目录

parents父目录序列,索引是直接的父目录

常用的一些路径操作命令

print(p.xxxx)

name目的最后一个部分

suffix 目录中最后一个部分的扩展名

stem目录的最后一个部分,没有后缀

suffixes 返回多个扩展名列表

with_suffix(suffix)补充扩展名到路径尾部,返回新的路径,扩展名若存在则无效

with_name(name) 替换目录最后一个部分并返回一个新的路径

p =path( )

p.  xxx     对一个文件目录进行判断,这个目录必须 实实在在的存在才能判断否则是False

cwd( ) 返回当前工作目录

home( )返回当前家目录

is_dir()是否是目录

is_file( )是否是普通文件

is_sysmlink( ) 是否是软连接

is_sockert( )是否是socket文件

is_block_device( ) 是否是块设备

is_char_device( )是否是字符设备

is_absolute( )是否是绝对路径

resolve( )返回一个路径,这个新路径就是当前Path对象的绝对路径,软链接会被解析

absolute( )也可以获取绝对路径,但是推荐使用resolve( )

exists( )目录或文件是否存在

rmdir( )删除空目录,没有提供判断目录为空的方法

as_uri( )将路径返回成URI,例如'file://etc/passwd'

touch(mode=0o666,exit_ok=True)创建一个文件
mkdir(mode=0o777,parents=False,ext\ist_ok=False)

parents,是否创建父目录,True创建,False不存在则报错,跟上exit_ok=bool参数,False:父目录路径存在报错,True:忽略这个错误,并不会提示

iterdir( )      迭代当前目录

使用glob去一个文件对象里匹配指定的文件

glob(匹配对象) 通配给定的模式

rglob(匹配对象)通配给定的模式,递归目录等同于 (**/*.py)

可以搭配文件路径使用

举例:

Path( ' . ' ).glob (*.py )

在当前工作目录下查找后缀为.py的文件对象

Path( ' . ' ).glob (*/*.py )

在当前工作目录下查找后缀为.py的文件对象且至少有一级目录

匹配

match(pattern)

模式匹配,成功返回True

Path('a/b.py').match('b/*.py')     #True
Path('a/b/c.py').match('a/*.py')     #False
Path('a/b/c.py').match('a/*/*.py')     #True
Path('a/b/c.py').match('a/**/*.py')     #True

文件操作

open(mode='r',buffering=-1,encoding=None,errors=None,newline=None)

使用方法类似内建函数open,返回一个文件对象

3.5增加的函数:

read_bytes() 以rb读取路径对应文键,并返回二进制流

read_text(encoding=None,errors=None)

以rt方式读取路径对应文件,返回文本

Path.write_bytes(data)

以wb方式写入数据到路径对应文件

write_text(data,encoding=None,errors=None)

以wt方式写入字符串到路径对应文件

文件的创建与相关操作

作者: 一个小菜鸡

如何利用路径与文件操作,来创建或者修改一个不存在的文件对象

from pathlib import Path
# 1.创建路径
p =Path('I:/filename1/file')
p.mkdir(mode=0o777,parents=True)     #mode=权限,父目录根据bool值来判断是否需要建立不存在的路径
# 2.创建或者打开一个文件,并对其内容进行阅读或者修改
with open('I:/filename1/file/file.txt','w+')as f:
f.write('hello,world')
print(f.read())

StringIO和BytesIO

作者: 一个小菜鸡

IO模块的类

from io import StringIO

内存中,开辟的一个文本模式的buffer,可以想文件对象一样操作它

当close方法被调用的时候,这个buffer会被释放

如何使用StringIO:

sio=StringIO( ) #像文件对象一样操作

使用 .getvalue( ) #无视指针,输出全部内容

使用StringIO的好处:

内存足够的情况下,一般的优化思路是少落地,减少磁盘IO的过程,可以大大提高程 序的运行效率

BytesIO:

如何使用BytesIO

from io import BytesIO

内存中,开辟的一个二进制模式的buffer,可以想文件对象一样操作它

当close方法被调用的时候,这个buffer会被释放

使用 .getvalue( ) #无视指针,输出全部内容

file-like对象

类文件对象,可以像文件对象一样操作

socket对象,输入输出对象(stdin,stout)都是类文件对象

from sys import stdout
f = stdout
print(type(f))
f.write('magedu.com')