csv文件、ini文件处理、序列化和反序列化、json

1.CSV文件

逗号分割值Comma-Separeted-Values
CSV是一个被行分隔符、列分隔符划分成行和列的文本文件。CSV不指定字符编码。
行分隔符为\r\n,最后一行可以没有换行符。
列分隔符为逗号或制表符
每一行都称为一条记录record
字段可以使用双引号括起来,也可以不使用,如果字段中出现了双引号、逗号、换行符必须使用双引号括起来,如果字段的值是双引号,使用两个双引号表示一个转义。
表头可选,和字段列对齐就行了。

1.1 手动生成CSV文件
from pathlib import Path
import csv

p1 = Path('c:/my.csv')
# csv文件
csv_body = """\
id,name,age,comment
1,tom,20,"i am 20"
2,jerry,18,"(""123"")"
3,ben,28,"这是
一  段
中文
"
"""

# with p1.open('w+') as f:
#     f.write(csv_body)
with p1.open() as f:
    body = csv.reader(f)
    for line in body:
        print(line)

# csv存在的问题就是无法确定字段的数据类型
1.2CSV模块

reader(csvfile, dialect=‘excel’, **fmtparams)
返回reader对象,是一个迭代器
默认使用excel方言,如下:

  • dilimiter列分隔符,逗号

  • lineterninator行分隔符\r\n

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

  • 双引号的处理:

  • doublequote双引号的处理,默认为True,如果碰到数据中有双引号,而quotechar也是双引号,True则使用两个双引号表示,False表示使用转义字符作为双引号的前缀。

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

  • write = csv.writer(f, doublequote=False, escapechar=’@’)遇到双引号则必须提供转义自字符
    quoting指定双引号的规则:

  • QUOTE_ALL所有字段

  • QUOTE_MINIMAL特殊字符字段,Excel方言使用该规则

  • QUOTE_NONNUMERIC非数字字段

  • QUOTE_NONE都不使用引号

writer(csvfile, dialect=‘excel’, **fmtparams)返回DictWriter的实例、主要方法有writerow、writerows
writerow(iterable)

p = Path('c:/my.csv')
with open(str(p)) as f:
    reader = csv.reader(f)
    print(next(reader))
    print(reader)
    for line in reader:
        print(line)


rows = [[4, 'curry', 31, 'my name is curry'],
        [5, 'klay', 28, 'my name is kaly'],
        [6, 'durant', 31, 'my name is durant'],
        [7, 'green', 28, 'my name is green'],
        (8, 'justin', 22, 'just\t"in'),
        "abcdefghi",
        ((1, ), (2, ))
        ]
row = rows[0]
with open(str(p), 'a') as f:
    writer = csv.writer(f)
    writer.writerow(row)
    writer.writerows(rows)

2.ini文件处理

[DEFAULT]
a = test

[mysql]
default-character-set = utf8

[mysqld]
test1 = 200
datadir = /dbserver/data
port = 33060
character-set-server = utf8
sql_mode = NO_ENGINE_SUBSTRITUTION,STRICT_TRANS_TABLES
c = True

[test]
test1 = 100

中括号里面的部分称为section,译为节、区、段。
每一个section内,都是key=value形成的键值对,key称为option选项。

注意这里的DEFAULT是缺省secstion的名字,必须大写。

2.1 configparser

  configparser模块的ConfigParser类就是用来操作。可以将section当做key,section存储着键值对组成的字典,可以把ini配置文件当做一个嵌套的字典,默认使用的是有序字典。
read(filenames, encoding=None)
读取ini文件,可以是单个文件,也可以是文件列表,可以指定文件编码。
sections()返回section列表,缺省section不包括在内。
has_section(section_name)判断section是否存在。
add_section(section_name_增加一个section
options(section)返回section的所有option,会追加缺省section的option
has_option(section, option), 判断section里面是否有option
get(section, option, *, raw=False, vars=None[, fallback])
从指定的section的选项上取值,如果找到返回,如果没找到就去找default段有没有。
getint(section, option, *, raw=False, vars=None[, fallback]) # 返回指定类型的数据
getfloat(section, option, *, raw=False, vars=None[, fallback])
getboolean(section, option, *, raw=False, vars=None[, fallback])

items(raw=False, vars=None) # 返回所有section名字及对象
items(section, raw=False, vars=None) # 返回指定的section的键值对组成的二元组
set(section, option, value)
section存在的情况下,写入opton=value,要求option、value必须是字符串
remove_section(section)
移除section及其所有的option
remove(section, option) # 移除指定section下的option
write(fileobject, space_around_delimiters=True)
将当前config的所有内容写入fileobject中,一般open函数使用w模式

# ini文件
import configparser


cfg = configparser.ConfigParser()
read_ok = cfg.read(['c:/mysql.ini', 'c:/t.ini', 'c:/list.ini'], encoding='utf-8')
print(read_ok)

print(cfg.sections(), cfg.default_section)  # 注意缺省的section不在sections()列表中
# print(cfg._sections)

print('~' * 30)

for k, v in cfg.items():
    print(type(k), k, type(v), v)
print('~' * 30)

for k, v in cfg.items('mysqld'):  # 指定section
    print(k, v)
print('~' * 30)

x = cfg.get('mysqld', 'a')  # 无法确定字段的类型
print(type(x), x)

x = cfg.get('mysql', 'a')
print(type(x), x)

x = cfg.getint('mysqld', 'port')  # 强制类型转换,整型
print(type(x), x)

x = cfg.get('mysqld', 'b', fallback=100)  # mysqld中没有key'b',使用fallback,100对应的类型就是int,'100',对应的就是字符串
print(type(x), x)

x = cfg.getboolean('mysqld', 'c', fallback='abc')  # 布尔型
print(type(x), x)

cfg.set('mysqld', 'c', 'True')  # value值必须是字符串

with open('c:/mysql.ini', 'w') as f:
    cfg.write(f)
print('~' * 40)

print(cfg['mysqld'])
print(cfg['mysqld']['a'])

if cfg.has_section('test'):
    cfg.remove_section('test')

cfg['test'] = {'test1': 100}  # 下面的方法设置section和option都可以
cfg['test']['test2'] = '123'  # 此处必须是字符串,否则会报错

if cfg.has_option('test', 'test2'):
    cfg.remove_option('test', 'test2')

print('test' in cfg)
print('test1' in cfg['test'])

# cfg['xyz']['abc'] = 'tests'  # 会报错,因为section'xyz'不存在

with open('c:/mysql.ini', 'w') as f:
    cfg.write(f)

3. 序列化和反序列化

3.1为什么要序列化?

内存中的字典、列表、集合以及各种对象,如何保存到一个文件中?
如果自己定义的类的实例,如何保存到一个文件中?
如何从文件中读取数据,并让他们在内存中再次恢复成自己对应的类的实例?
这就需要设计一套协议,按照某种规则,把内存中数据保存到文件中,文件是一个字节序列,所以必须把数据转换成字节序列,输出到文件,这就是序列化。反之,从文件的字节序列恢复到内存并且还是原来的类型,就是反序列化。

3.2 序列化与反序列化定义

serialization序列化:将内存中对象存储下来,把它变成一个一个字节。->转化成二进制
deserialization反序列化:将文件的一个一个字节恢复成内存中对象。
序列化保存到文件就是持久化
可以将数据序列化后持久化,或者网络传输;也可以将从文件中或者网络接收到的字节序列反序列化

3.3 pickle库

序列化与反序列化

# pickle库
import pickle

a = 97
a1 = 99
b = 'c'
c = [48, 'abc']
d = {'aaaaaaaaa': 'ddd', 'bbbbbbbbbbbb': 1}

with open('c:/ser', 'wb+') as f:
    pickle.dump(a, f)  # dump将a序列化
    pickle.dump(a1, f)
    pickle.dump(b, f)
    pickle.dump(c, f)
    pickle.dump(d, f)

with open('c:/ser', 'rb+') as f:
    for i in range(5):
        x = pickle.load(f)  # load反序列化
        print(type(x), x)
        if isinstance(x, list):
            print(id(c), id(x))  # 列表c跟列表x不是同一个列表了
"""<class 'int'> 97
<class 'int'> 99
<class 'str'> c
<class 'list'> [48, 'abc']
43921480 44030536
<class 'dict'> {'aaaaaaaaa': 'ddd', 'bbbbbbbbbbbb': 1}
"""
class A:
    B = 'abc'

    def __init__(self):
        self.aaaa = 'abc'

    def bbbbbbbbbbbbbb(self):
        print('++++++++++++++++++++')

    def show(self):
        print('abcdefg')


a = A()
a.bbbbbbbbbbbbbb()

s = pickle.dumps(a)
print(type(s))
print(s)

with open('c:/ser1', 'wb') as f:
    f.write(s)

with open('c:/ser1', 'rb') as f:
    x = pickle.load(f)
    print(type(x))
    print(x, id(x), id(a))
    x.bbbbbbbbbbbbbb()

with open('c:/ser1', 'rb') as f:
    x = pickle.load(f)
    print(type(x))
    print(x, id(x))
    x.bbbbbbbbbbbbbb()
    x.show()

  上例中,只序列化了类A,aaaa和abc,类中的定义的方法没有序列化,因为他们都是不变的,反序列化的时候,找到类就可以恢复对象了,之所以还序列化了aaaa和abc,是因为它们是实例对象的,每一个实例对象都是不一样的,所以这些数据需要序列化。

3.4 序列化应用

  一般来说,本地序列化的情况,应用较少,大多数场景都是应用在网络传输中。将数据序列化后通过网络传输到远程节点,远程服务器上的服务将接收到数据反序列化后,就可以使用了。但是,注意一点,远程接收端,反序列化时必须有对应的数据类型,否则就会报错。尤其是自定义的类,必须远程得有一致的定义。
  现在,大多数项目,都不是单机的,也不是单服务的,需要多个程序之间配合,需要通过网络将数据传送到其他节点上去,这就需要大量的序列化和反序列化过程。
  但是问题是 ,python程序之间还可以都是用pickle解决序列化、反序列化,如果是跨平台、跨语言、跨协议pickle就不太合适了,就需要公共的协议。例如像XML、Json、ProtocolBuffer等。

4. Json

  JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式。它基于ECMAScript(w3c组织制定的JS规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。

4.1 json的数据类型
4.1.1 值

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

4.1.1.1 字符串

双引号引起来的任意字符的组合,可以有转义字符。

4.1.1.2 数值

有正负、有整数、浮点数

4.1.1.3 对象 ——>对应python中的字典

无序的键值对的集合
格式: {key1: value1, key2: value2…keyn: valuen}
key必须一个字符串,需要双引号包围这个字符串
value可以是任意合法值
对象

4.1.1.4 数组 ——> 对应python中的列表

有序值的集合
格式: [value1, value2, … valuen]
数组

4.2 json模块

Python支持少量的内建数据类型到json类型的转换。
python常用方法:
常用方法

import json
from configparser import ConfigParser

cfg = ConfigParser()

read_ok = cfg.read('c:/mysql.ini')
print(read_ok)

d = {}

for section in cfg.sections():
    print(section, cfg.items(section))
    d[section] = dict(cfg.items(section))
print(d)

with open('c:/mysql.json', 'w+') as f:
    json.dump(d, f)
import json

d = {'name': 'curry', 'age': 31, 'intrest': ('music', 'movie'), 'class': ['python']}
j = json.dumps(d)
print(j, type(j))
# {"name": "curry", "age": 31, "intrest": ["music", "movie"], "class": ["python"]} <class 'str'>

d1 = json.loads(j)
print(d1)
# {'name': 'curry', 'age': 31, 'intrest': ['music', 'movie'], 'class': ['python']}
print(id(d), id(d1))
# 31161584 32006288 注意两个不在是同一个对象了

  一般json编码的数据很少落地,数据都是通过网络传输。传输的时候,要考虑压缩它。本质上来说他就是个文本,就是字符串。

4.3 MessagePack

  MessagePack是一个基于二进制高效的对象序列化类库,可用于跨语言通信。它可以像JSON那样,在许多种语言之间交换结构对象。但是它比JSON更快速也更轻巧。支持python、Ruby、Java、C/C++等众多语言,兼容json和pickle。
安装: $ pip install msgpack # terminal窗口中安装

import json
import pickle
import msgpack

d = {'a': 1, 'b': 'abc', 'c': ['1', '2'], 'd': {'e': (50, 500), 'f': (1, 2, 3)}}
x = json.dumps(d)  # set不可序列化
print(type(d), type(x))
y = x.replace(' ', '')
print(len(y), y)  # 长度为62

p = pickle.dumps(d)
print(len(p), p)  # 长度为111

d1 = json.loads(x)
print(type(d1))
print(d1)

print(id(d), id(d1))

data = msgpack.dumps(d)  # 二进制
print(len(data), data)  # 最省内存,长度为33
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值