Python语法基础之. Task07 文件与文件系统(9-10/17)

Python基础—— Task07 文件与文件系统

  • 1. 文件读写
    • 1.1 读文件
    • 1.2 open() 方法总结
    • 1.3 写文件
    • 2. 内存读写
    • 2.1 StringIO
    • 2.2 BytesIO
  • 3. OS 文件/目录方法
    • 3.1 OS 模块中关于文件/目录常用的函数使用方法
    • 3.2 os 模块常用方法总结
  • 4. 序列化
    • 4.1 序列化基础知识
    • 4.2 (补充)JSON
  • 写在最后

1. 文件读写

读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。
读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

1.1 读文件

要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符。
举例:

f=open('D:\\learnpython\\hello.py','r')

(补充)JupyterNotebook实例:


标示符’r’表示读;如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息

>>>f=open('/Users/michael/notfound.txt', 'r')
Traceback (most recent call last):
  File "", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '/Users/michael/notfound.txt'

如果文件打开成功,则调用read()方法可以一次读取文件的全部内容,Python把内容用一个str对象表示

>>> f.read()
'Hello, world!'

调用close()方法关闭文件。注意:文件使用完毕后必须关闭(因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量是有限的)

>>> f.close()

由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。
所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现

try:
    f = open('/path/to/file', 'r')
    print(f.read())
finally:
    if f:
        f.close()

还有一种更加单的方法:Python引入了with语句来自动帮我们调用close()方法。

  • 优势:这和前面的try … finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法
with open('/path/to/file', 'r') as f:
    print(f.read())

三种读文件的方式

  • read(size) 每次最多读取size个字节的内容
  • readline() 每次读取一行的内容
  • readlines() 读取所有内容,并按行返回list

一般来讲,如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便

for line in f.readlines():
    print(line.strip())

补充
1、file-like Object
open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object。除了file外,还可以是内存的字节流,网络流,自定义流等等。file-like Object不要求从特定类继承,只要写个read()方法就行。
StringIO就是在内存中创建的file-like Object,常用作临时缓冲。

2、二进制文件
前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频等等,用'rb'模式打开文件即可:

>>> f = open('/Users/michael/test.jpg', 'rb')
>>> f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节

3、字符编码
要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
>>> f.read()
'测试'

遇到有些编码不规范的文件,如遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。此时open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略

>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')

我们选择errors=‘ignore’,那么如果出现非法编码字符,会直接忽略

1.2 open() 方法总结

Python open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError
注意:

  • 使用 open()方法一定要保证关闭文件对象,即调用 close()方法。

open()函数常用形式是接收两个参数:文件名(file)和模式(mode)

open(file, mode='r')

完整的语法格式为:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

参数说明:

  • file: 必需,文件路径(相对或者绝对路径)。
  • mode: 可选,文件打开模式
  • buffering: 设置缓冲
  • encoding: 一般使用utf8
  • errors: 报错级别
  • newline: 区分换行符
  • closefd: 传入的file参数类型
  • opener:

其中,mode 参数有:

模式 描述
t 文本模式 (默认)。
x 写模式,新建一个文件,如果该文件已存在则会报错。
b 二进制模式。
+ 打开一个文件进行更新(可读可写)。
U 通用换行模式(Python 3 不支持)。
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

特别的,默认为文本模式,如果要以二进制模式打开,加上b

file 对象
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:

file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:

序号 方法及描述
1

file.close()

关闭文件。关闭后文件不能再进行读写操作。

2

file.flush()

刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。

3

file.fileno()

返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。

4

file.isatty()

如果文件连接到一个终端设备返回 True,否则返回 False。

5

file.next()

Python 3 中的 File 对象不支持 next() 方法。

返回文件下一行。

6

file.read([size])

从文件读取指定的字节数,如果未给定或为负则读取所有。

7

file.readline([size])

读取整行,包括 "\n" 字符。

8

file.readlines([sizeint])

读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。

9

file.seek(offset[, whence])

移动文件读取指针到指定位置

10

file.tell()

返回文件当前位置。

11

file.truncate([size])

从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 Widnows 系统下的换行代表2个字符大小。

12

file.write(str)

将字符串写入文件,返回的是写入的字符长度。

13

file.writelines(sequence)

向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。

1.3 写文件

写文件和读文件是一样的,区别是调用open()函数时,传入标识符’w’或者’wb’表示写文本文件或写二进制文件。

>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()

我们不断使用write写入的内容先被存放在内存中,python会在空闲时间慢慢写入,只有使用了close()方法后内存中所有内容才会被写入磁盘中——所以一不要忘记close,否则可能会导致内容部分丢失。
使用‘w’模式,新内容会覆盖原来的内容,如果需要追加内容可以使用‘a’模式写入。

为了保证每次open后,我们都关闭文件——还是要使用with语句

with open('/Users/michael/test.txt', 'w') as f:
    f.write('Hello, world!')
  • 若要写入特定编码的文本文件,open()函数需传入encoding参数,将字符串自动转换成指定编码
  • 以’w’模式写入文件时,如果文件已存在,会直接覆盖。如果希望追加到文件末尾?可以传入’a’以**追加(append)**模式写入。

2. 内存读写

很多时候,数据读写不一定是文件,也可以在内存中读写。
StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口。

2.1 StringIO

顾名思义就是在内存中读写str。

一、 写入
要把str写入StringIO,我们需要先创建一个StringIO,然后像文件一样写入即可:

>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())
hello world!
  • getvalue()方法用于获得写入后的str

二、读取
读取StringIO,可以用一个str初始化StringIO,然后像读文件一样读取:

>>> from io import StringIO
>>> f = StringIO('Hello!\nHi!\nGoodbye!')
>>> while True:
...     s = f.readline()
...     if s == '':
...         break
...     print(s.strip())
...
Hello!
Hi!
Goodbye!

2.2 BytesIO

StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO
一、写入
BytesIO实现了在内存中读写bytes,我们创建一个BytesIO,然后写入一些bytes:

>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))
6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'
  • 请注意,写入的不是str,而是经过UTF-8编码的bytes。

二、读取
StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取:

>>> from io import BytesIO
>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
>>> f.read()
b'\xe4\xb8\xad\xe6\x96\x87'

3. OS 文件/目录方法

3.1 OS 模块中关于文件/目录常用的函数使用方法

本节主要摘自、本地实现 刻意练习:Python基础 – Task07. 文件与文件系统 特此感谢!

”我们所知道常用的操作系统就有:Windows,Mac OS,Linu,Unix等,这些操作系统底层对于文件系统的访问工作原理是不一样的,因此你可能就要针对不同的系统来考虑使用哪些文件系统模块……,这样的做法是非常不友好且麻烦的,因为这样就意味着当你的程序运行环境一改变,你就要相应的去修改大量的代码来应对。“

有了OS(Operation System)模块,我们不需要关心什么操作系统下使用什么模块,OS模块会帮你选择正确的模块并调用

  • os.getcwd() 用于返回当前工作目录
  • os.chdir(path) 用于改变当前工作目录到指定的路径
import os

path = '/Users/iz'
print("当前工作目录 : %s" % os.getcwd())
# 当前工作目录 : /Users/iz/PycharmProjects/17DaysPythonBasicTraining
os.chdir(path)
print("目录修改成功 : %s" % os.getcwd())
# 目录修改成功 : /Users/iz
  • os.listdir(path)返回path指定的文件夹包含的文件或文件夹的名字的列表
import os

dirs = os.listdir()
for item in dirs:
    print(item)
  • os.mkdir(path)创建单层目录,如果该目录已存在抛出异常
import os

if os.path.isdir(r'.\b') is False:
    os.mkdir(r'.\B')
    os.mkdir(r'.\B\A')

os.mkdir(r'.\C\A') # FileNotFoundError
  • os.makedirs(path)用于递归创建多层目录,如果该目录已存在抛出异常
import os
os.makedirs(r'.\E\A')
  • os.remove(path)用于删除指定路径的文件;如果指定的路径是一个目录,将抛出 OSError
import os

print("目录为: %s" % os.listdir(r'/Users/iz/test.rtf'))
os.remove(r'/Users/iz/test.rtf')
print("目录为: %s" % os.listdir(r'/Users/iz/test.rtf'))
  • os.rmdir(path)用于删除单层目录。仅当这文件夹是空的才可以, 否则, 抛出OSError
import os

print("目录为: %s" % os.listdir(r'.\E'))
os.rmdir(r'.\E\A')
print("目录为: %s" % os.listdir(r'.\E'))
  • os.removedirs(path)递归删除目录,从子目录到父目录逐层尝试删除,遇到目录非空则抛出异常
import os

print("目录为: %s" % os.listdir(os.getcwd()))
os.removedirs(r'.\E\A')  # 先删除A 然后删除E
print("目录为: %s" % os.listdir(os.getcwd()))
  • os.rename(src, dst)方法用于命名文件或目录,从 srcdst,如果 dst 是一个存在的目录, 将抛出 `OSError
import os

print("目录为: %s" % os.listdir(os.getcwd()))
os.rename("test", "test2")
print("重命名成功。")
print("目录为: %s" % os.listdir(os.getcwd()))
  • os.system(command)运行系统的shell命令(将字符串转化成命令)
import os

path = os.getcwd() + '\\a.py'
a = os.system(r'python %s' % path)

os.system('calc')  # 打开计算器
  • os.curdir指代当前目录(.
  • os.pardir指代上一级目录(..
  • os.sep输出操作系统特定的路径分隔符(win下为\,Linux下为/
  • os.linesep当前平台使用的行终止符(win下为\r\n,Linux下为\n
  • os.name指代当前使用的操作系统(包括:‘mac’,‘nt’)
import os

print(os.curdir)  # .
print(os.pardir)  # ..
print(os.sep)  # \
print(os.linesep)
print(os.name)  # nt
  • os.path.basename(path)去掉目录路径,单独返回文件名
  • os.path.dirname(path)去掉文件名,单独返回目录路径
  • os.path.join(path1[, path2[, …]])path1path2 各部分组合成一个路径名
  • os.path.split(path)分割文件名与路径,返回(f_path,f_name)元组。如果完全使用目录,它会将最后一个目录作为文件名分离,且不会判断文件或者目录是否存在。
  • os.path.splitext(path)分离文件名与扩展名,返回(f_path,f_name)元组
import os

# 返回文件名
print(os.path.basename(r'C:\test\lsgo.txt'))  # lsgo.txt
# 返回目录路径
print(os.path.dirname(r'C:\test\lsgo.txt'))  # C:\test
# 将目录和文件名合成一个路径
print(os.path.join('C:\\', 'test', 'lsgo.txt'))  # C:\test\lsgo.txt
# 分割文件名与路径
print(os.path.split(r'C:\test\lsgo.txt'))  # ('C:\\test', 'lsgo.txt')
# 分离文件名与扩展名
print(os.path.splitext(r'C:\test\lsgo.txt'))  # ('C:\\test\\lsgo', '.txt')
  • os.path.getsize(file)返回指定文件大小,单位是字节。
  • os.path.getatime(file)返回指定文件最近的访问时间
  • os.path.getctime(file)返回指定文件的创建时间
  • os.path.getmtime(file)返回指定文件的最新的修改时间
  • 浮点型秒数,可用time模块的gmtime()localtime()函数换算
import os
import time

file = r'.\lsgo.txt'
print(os.path.getsize(file))  # 30
print(os.path.getatime(file))  # 1565593737.347196
print(os.path.getctime(file))  # 1565593737.347196
print(os.path.getmtime(file))  # 1565593797.9298275
print(time.gmtime(os.path.getctime(file)))
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=12, tm_hour=7, tm_min=8, tm_sec=57, tm_wday=0, tm_yday=224, tm_isdst=0)
print(time.localtime(os.path.getctime(file)))
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=12, tm_hour=15, tm_min=8, tm_sec=57, tm_wday=0, tm_yday=224, tm_isdst=0)
  • os.path.exists(path)判断指定路径(目录或文件)是否存在
  • os.path.isabs(path)判断指定路径是否为绝对路径
  • os.path.isdir(path)判断指定路径是否存在且是一个目录
  • os.path.isfile(path)判断指定路径是否存在且是一个文件
  • os.path.islink(path)判断指定路径是否存在且是一个符号链接
  • os.path.ismount(path)判断指定路径是否存在且是一个悬挂点
  • os.path.samefile(path1,path2)判断path1和path2两个路径是否指向同一个文件
import os

print(os.path.ismount('D:\\'))  # True
print(os.path.ismount('D:\\Test'))  # False

3.2 os 模块常用方法总结

以下内容来自 Runoob Python3教程——Python3 OS 文件/目录方法 特此感谢!

序号 方法及描述
1 os.access(path, mode) 检验权限模式
2 os.chdir(path) 改变当前工作目录
3 os.chflags(path, flags) 设置路径的标记为数字标记。
4 os.chmod(path, mode) 更改权限
5 os.chown(path, uid, gid) 更改文件所有者
6 os.chroot(path) 改变当前进程的根目录
7 os.close(fd) 关闭文件描述符 fd
8 os.closerange(fd_low, fd_high) 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略
9 os.dup(fd) 复制文件描述符 fd
10 os.dup2(fd, fd2) 将一个文件描述符 fd 复制到另一个 fd2
11 os.fchdir(fd) 通过文件描述符改变当前工作目录
12 os.fchmod(fd, mode) 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。
13 os.fchown(fd, uid, gid) 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。
14 os.fdatasync(fd) 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。
15 [os.fdopen(fd, mode[, bufsize]]) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象
16 os.fpathconf(fd, name) 返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。
17 os.fstat(fd) 返回文件描述符fd的状态,像stat()。
18 os.fstatvfs(fd) 返回包含文件描述符fd的文件的文件系统的信息,Python 3.3 相等于 statvfs()。
19 os.fsync(fd) 强制将文件描述符为fd的文件写入硬盘。
20 os.ftruncate(fd, length) 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。
21 os.getcwd() 返回当前工作目录
22 os.getcwdu() 返回一个当前工作目录的Unicode对象
23 os.isatty(fd) 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。
24 os.lchflags(path, flags) 设置路径的标记为数字标记,类似 chflags(),但是没有软链接
25 os.lchmod(path, mode) 修改连接文件权限
26 os.lchown(path, uid, gid) 更改文件所有者,类似 chown,但是不追踪链接。
27 os.link(src, dst) 创建硬链接,名为参数 dst,指向参数 src
28 os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表。
29 os.lseek(fd, pos, how) 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效
30 os.lstat(path) 像stat(),但是没有软链接
31 os.major(device) 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。
32 os.makedev(major, minor) 以major和minor设备号组成一个原始设备号
33 [os.makedirs(path, mode]) 递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。
34 os.minor(device) 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。
35 [os.mkdir(path, mode]) 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。
36 [os.mkfifo(path, mode]) 创建命名管道,mode 为数字,默认为 0666 (八进制)
37 [os.mknod(filename, mode=0600, device]) 创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。
38 [os.open(file, flags, mode]) 打开一个文件,并且设置需要的打开选项,mode参数是可选的
39 os.openpty() 打开一个新的伪终端对。返回 pty 和 tty的文件描述符。
40 os.pathconf(path, name) 返回相关文件的系统配置信息。
41 os.pipe() 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写
42 [os.popen(command, mode[, bufsize]]) 从一个 command 打开一个管道
43 os.read(fd, n) 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。
44 os.readlink(path) 返回软链接所指向的文件
45 os.remove(path) 删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。
46 os.removedirs(path) 递归删除目录。
47 os.rename(src, dst) 重命名文件或目录,从 src 到 dst
48 os.renames(old, new) 递归地对目录进行更名,也可以对文件进行更名。
49 os.rmdir(path) 删除path指定的空目录,如果目录非空,则抛出一个OSError异常。
50 os.stat(path) 获取path指定的路径的信息,功能等同于C API中的stat()系统调用。
51 [os.stat_float_times(newvalue]) 决定stat_result是否以float对象显示时间戳
52 os.statvfs(path) 获取指定路径的文件系统统计信息
53 os.symlink(src, dst) 创建一个软链接
54 os.tcgetpgrp(fd) 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组
55 os.tcsetpgrp(fd, pg) 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。
56 os.tempnam([dir[, prefix]]) Python3 中已删除。 返回唯一的路径名用于创建临时文件。
57 os.tmpfile() Python3 中已删除。 返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。
58 os.tmpnam() Python3 中已删除。 为创建一个临时文件返回一个唯一的路径
59 os.ttyname(fd) 返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。
60 os.unlink(path) 删除文件路径
61 os.utime(path, times) 返回指定的path文件的访问和修改的时间。
62 [os.walk(top, topdown=True[, οnerrοr=None[, followlinks=False]]]) 输出在文件夹中的文件名通过在树中游走,向上或者向下。
63 os.write(fd, str) 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度
64 os.path 模块 获取文件的属性信息。

4. 序列化

Python语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合Web标准,就可以使用json模块
“json模块的dumps()loads()函数是定义得非常好的接口的典范:当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性。” ——廖雪峰

4.1 序列化基础知识

  • 变量从内存中变成可存储或传输的过程称之为序列化(在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等)
  • 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上
  • 变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling

python用pickle模块实现序列化

  • pickle.dumps()可以把任意对象序列化成一个bytes,然后把bytes写入文件
  • 可以用pickle.dump()直接把对象序列化后写入一个file-like object,这样就可以把对象写入到磁盘了
  • pickle.load()的方法把file-like object 中直接反序列划出对象
  • pickle可能有不兼容的问题,所以只能用于保存不重要的数据

通过 pickle 模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储。

通过 pickle 模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

pickle模块中最常用的函数为:
pickle.dump(obj, file, [,protocol]) 将obj对象序列化存入已经打开的file中

  • obj:想要序列化的obj对象
  • file:文件名称
  • protocol:序列化使用的协议。如果该项省略,则默认为0。如果为负值
  • HIGHEST_PROTOCOL,则使用最高的协议版本

pickle.load(file) 将file中的对象序列化读出

  • file:文件名称
import pickle

dataList = [[1, 1, 'yes'],
            [1, 1, 'yes'],
            [1, 0, 'no'],
            [0, 1, 'no'],
            [0, 1, 'no']]
dataDic = {0: [1, 2, 3, 4],
           1: ('a', 'b'),
           2: {'c': 'yes', 'd': 'no'}}

# 使用dump()将数据序列化到文件中
fw = open(r'.\test.txt', 'wb')

# Pickle the list using the highest protocol available.
pickle.dump(dataList, fw, -1)

# Pickle dictionary using protocol 0.
pickle.dump(dataDic, fw)
fw.close()

# 使用load()将数据从文件中序列化读出
fr = open('test.txt', 'rb')
data1 = pickle.load(fr)
print(data1)
data2 = pickle.load(fr)
print(data2)
fr.close()

# [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
# {0: [1, 2, 3, 4], 1: ('a', 'b'), 2: {'c': 'yes', 'd': 'no'}}

然而上面这个,本地还没有成功

4.2 (补充)JSON

要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON:因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。

JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:

JSON类型 Python类型
{} dict
[] list
“string” str
1234.56 int或float
true/false True/False
null None

Python内置的json模块提供Python对象到JSON格式的转换

  • 将Python对象变成一个JSON:
>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'

dumps()方法返回一个str,内容就是标准的JSON。类似的,dump()方法可以直接把JSON写入一个file-like Object

要把JSON反序列化为Python对象,用loads()或者对应的load()方法

  • 前者把JSON的字符串反序列化
  • 后者从file-like Object中读取字符串并反序列化:
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}

由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str与JSON的字符串之间转换

JSON 进阶
参考:
1、入门-廖雪峰博客
2、入门-Runoob博客
3、完成-JSON文档

写在最后

很多都是用法贴了出来。诚然作为查询目录也不错,但还是有时间都本地实现一下,而且争取 Windows/Mac 双重实现,算是立个Flag。

你可能感兴趣的:(Python,Python基础)