第零章 学前准备
第一章 数据结构 – 基本数据类型
第一章 数据结构 – 字符串
第一章 数据结构 – 列表、元组和切片
第一章 数据结构 – 字典
第一章 数据结构 – 集合
第一章 – 数组、队列、枚举
第一章 数据结构 – 序列分类
第二章 控制流程
第三章 函数也是对象 – 函数定义以及参数
第三章 函数也是对象 – 高阶函数以及装饰器
第三章 函数也是对象 – lambda 表达式、可调用函数及内置函数
第四章 面向对象编程 – 自定义类、属性、方法和函数
第四章 面向对象编程–魔术方法1
第四章 面向对象编程 – 魔术方法2
第四章 面向对象编程 – 可迭代的对象、迭代器和生成器
第四章 面向对象编程 – 继承、接口
第四章 面向对象编程 – 对象引用
第四章 面向对象编程–案例
第五章 文件操作
文章目录
- 第五章 文件操作
-
- 5.1 `open` 函数
- 5.2 `class io.TextIOBase`
- 5.3 案例
- 5.4 [Json文件操作](http://www.json.org.cn/)
- 5.5 [数据压缩和存档](https://docs.python.org/3/library/archiving.html)
第五章 文件操作
5.1 open
函数
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
打开 file
并返回对应的 file object
。如果该文件不能打开,则触发 OSError。
5.1.1 file
file
是一个 path-like object
,表示将要打开的文件的路径(绝对路径或者当前工作目录的相对路径),也可以是要被封装的整数类型文件描述符。(如果是文件描述符,它会随着返回的 I/O
对象关闭而关闭,除非 closefd
被设为 False
。)
5.1.2 mode
mode
是一个可选字符串,用于指定打开文件的模式。默认值是 'r'
,这意味着它以文本模式打开并读取。其他常见模式有:写入 'w'
(截断已经存在的文件);排它性创建 'x'
;追加写 'a'
(在 一些 Unix
系统上,无论当前的文件指针在什么位置,所有 写入都会追加到文件末尾)。在文本模式,如果 encoding
没有指定,则根据平台来决定使用的编码:使用 locale.getpreferredencoding(False)
来获取本地编码。(要读取和写入原始字节,请使用二进制模式并不要指定 encoding
。)可用的模式有:
字符 | 含义 |
---|---|
r | 读取(默认) |
w | 写入,并先截断文件 |
x | 排它性创建,如果文件已存在则失败 |
a | 写入,如果文件存在则在末尾追加 |
b | 二进制模式 |
t | 文本模式(默认) |
+ | 更新磁盘文件(读取并写入) |
Python
区分二进制和文本 I/O
。以二进制模式打开的文件(包括 mode
参数中的 'b'
)返回的内容为 bytes
对象,不进行任何解码。在文本模式下(默认情况下,或者在 mode 参数中包含 't'
)时,文件内容返回为 str
,首先使用指定的 encoding
(如果给定)或者使用平台默认的的字节编码解码。
5.1.3 buffering
buffering
是一个可选的整数,用于设置缓冲策略。传递 0
以切换缓冲关闭(仅允许在二进制模式下),1选择行缓冲(仅在文本模式下可用),并且 >1
的整数以指示固定大小的块缓冲区的大小(以字节为单位)。如果没有给出 buffering
参数,则默认缓冲策略的工作方式如下:
- 二进制文件以固定大小的块进行缓冲;使用启发式方法选择缓冲区的大小,尝试确定底层设备的“块大小”或使用
io.DEFAULT_BUFFER_SIZE
。在许多系统上,缓冲区的长度通常为4096
或8192
字节。 - “交互式”文本文件( isatty() 返回 True 的文件)使用行缓冲。其他文本文件使用上述用于二进制文件的策略。
5.1.4 encoding
是用于解码或编码文件的编码的名称。这应该只在文本模式下使用。默认编码是依赖于平台的,但可以使用任何Python支持的 text encoding
。有关支持的编码列表,可以参阅参阅 codecs 模块。
5.1.5 errors
errors
是一个可选的字符串参数,用于指定如何处理编码和解码错误。不能在二进制模式下使用。可以使用各种标准错误处理程序(列在错误处理方案 ),但是使用 codecs.register_error()
注册的任何错误处理名称也是有效的。标准名称包括:
- 如果存在编码错误,
'strict'
会引发ValueError
异常。 默认值None
具有相同的效果。 'ignore'
忽略错误。请注意,忽略编码错误可能会导致数据丢失。'replace'
会将替换标记(例如'?'
)插入有错误数据的地方。'surrogateescape'
将表示任何不正确的字节作为Unicode
专用区中的代码点,范围从U+DC80
到U+DCFF
。当在写入数据时使用surrogateescape
错误处理程序时,这些私有代码点将被转回到相同的字节中。这对于处理未知编码的文件很有用。- 只有在写入文件时才支持 ‘xmlcharrefreplace’。编码不支持的字符将替换为相应的XML字符引用 &#nnn; 。
- ‘backslashreplace’ 用Python的反向转义序列替换格式错误的数据。
'namereplace'
(也只在编写时支持)用\N{...}
转义序列替换不支持的字符。
5.1.6 newline
newline
控制 universal newlines
模式如何生效(它仅适用于文本模式)。它可以是 None
, ''
, '\n'
, '\r'
和 '\r\n'
。它的工作原理: 从流中读取输入时,如果 newline
为 None,则启用通用换行模式。输入中的行可以以 '\n'
, '\r'
或 '\r\n'
结尾,这些行被翻译成 '\n'
在返回呼叫者之前。如果它是 ''
,则启用通用换行模式,但行结尾将返回给调用者未翻译。如果它具有任何其他合法值,则输入行仅由给定字符串终止,并且行结尾将返回给未调用的调用者。将输出写入流时,如果 newline
为 None
,则写入的任何 '\n'
字符都将转换为系统默认行分隔符 os.linesep
。如果 newline
是 ''
或 '\n'
,则不进行翻译。如果 newline
是任何其他合法值,则写入的任何 '\n'
字符将被转换为给定的字符串。
5.2 class io.TextIOBase
class io. TextIOBasepp文本流的基类,当 open
函数以文本模式打开时,返回的就是该类的子类或该类的子类。
close()
:刷新并关闭此流。如果文件已经关闭,则此方法无效。文件关闭后,对文件的任何操作(例如读取或写入)都会引发ValueError
。为方便起见,允许多次调用此方法。但是,只有第一个调用才会生效。read(size=-1)
:从流中读取至多size
个字符并以单个str
的形式返回。 如果size
为负值或None
,则读取至EOF
。readline(size=-1)
:读取至换行符或EOF
并返回单个str
。 如果流已经到达EOF
,则将返回一个空字符串。如果指定了size
,最多将读取size
个字符。seek(offset, whence=SEEK_SET)
:将流位置改为给定的偏移位置offset
。 计算offset
方法取决于whence
形参。whence
的默认值为SEEK_SET
。SEEK_SET
或0
: 从流的开始位置起查找(默认值);offset
必须为正数或为零。SEEK_CUR
或1
: “查找” 到当前位置;offset
可以为负数。SEEK_END
或2
: 查找到流的末尾;offset
通常为负数。
tell()
:以不透明数字形式返回当前流的位置。 该数字通常并不代表下层二进制存储中对应的字节数。write(s)
:将字符串s
写入到流并返回写入的字符数。writelines(lines)
:将行列表写入到流。 不会添加行分隔符,因此通常所提供的每一行都带有末尾行分隔符。seekable()
:如果流支持随机访问则返回True
。writable()
:如果流支持写入则返回 True。readable()
:如果可以读取流,则返回 True 。
5.3 案例
fp=open(file="test.txt", mode="w", encoding='utf8')
fp.write('2022年12月7日\n2022年12月7日')
fp.close()
fp=open(file="test.txt", mode="r", encoding='utf8')
print(fp.read())
fp.close()
print("*"*20)
fp=open(file="test.txt", mode="w", encoding='utf8')
fp.writelines(['2022年12月7日','2022年12月7日'])
fp.close()
fp=open(file="test.txt", mode="r", encoding='utf8')
print(fp.read())
fp.close()
print("*"*20)
fp=open(file="test.txt", mode="w", encoding='utf8')
fp.writelines("\n".join(['2022年12月7日','2022年12月7日']))
fp.close()
with open(file="test.txt", mode="r", encoding='utf8') as fp:
print(fp.readlines())
2022年12月7日
2022年12月7日
********************
2022年12月7日2022年12月7日
********************
['2022年12月7日\n', '2022年12月7日']
5.4 Json文件操作
5.4.1 什么是Json
JSON(JavaScript Object Notation)
是一种轻量级的数据交换格式。它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。它是基于 JavaScript Programming Language
, Standard ECMA-262 3rd Edition - December 1999
的一个子集。JSON
采用完全独立于程序语言的文本格式,但是也使用了类C
语言的习惯(包括C
, C++
, C#
, Java
, JavaScript
, Perl
, Python
等)。这些特性使JSON
成为理想的数据交换语言。
5.4.2 Json数据模型
5.4.2.1 数据结构
-
对象
(Object)
:“名称/值”对的集合(A collection of name/value pairs)
。不同的编程语言中,它被理解为对象(object
),纪录(record
),结构(struct
),字典(dictionary
),哈希表(hash table
),有键列表(keyed list
),或者关联数组 (associative array
)。语法和Python字典很像,在{ }
中书写 -
数组(Array)
:值的有序列表(An ordered list of values
)。在大部分语言中,它被实现为数组(array
),矢量(vector
),列表(list
),序列(sequence
)。语法和Python
列表很像,在[ ]
中书写。
5.4.2.2 基本数据类型
- 字符串(
string
):由双引号括包围的由任意数量Unicode字符的集合,使用反斜线转义。 - 数值(
number
):与python中float
和int
很像,但是JSON
的数值没有使用八进制与十六进制格式。 - 布尔类型(
bool
):true
和false
; - null值
5.4.2.3 举例
下面内容保存在文件:movies.json
中。
{
"movies": [
{
"name": "The Shawshank Redemption",
"rating": 9.7,
"category": [
6,
9
],
"showed": true
},
{
"name": "Forrest Gump",
"rating": 9.5,
"category": [
2,
9
],
"showed": true
},
{
"name": "Titanic",
"rating": null,
"category": [
2,
9
],
"showed": false
}
],
"category": {
"Comedy": 0,
"Thriller": 1,
"Romance": 2,
"Horror": 3,
"Action": 4,
"Sci-Fi": 5,
"Crime": 6,
"War": 7,
"suspense ": 8,
"drama": 9
}
}
5.4.3 json — JSON 编码和解码器
5.4.3.1 编解码
- 解码:默认情况下,解码执行以下翻译:
JSON | Python |
---|---|
object--对象 | dict |
array | list--列表 |
string | str |
number(int) | int |
number(real) | flaot |
true | True |
false | False |
null | None |
- 编码:默认情况下,编码执行以下翻译:
Python | JSON |
---|---|
dict | object--对象 |
list,tuple | array |
str | string |
int,float,int和float派生枚举 | number |
True | true |
False | false |
None | null |
5.4.3.2 基本使用 API
5.4.3.2.1 json.load
json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
使用这个转换表 将 fp
(一个支持 .read()
并包含一个 JSON
文档的 text file
或者 binary file
) 反序列化为一个 Python
对象。如果反序列化的数据不是有效 JSON 文档,引发 JSONDecodeError 错误。
fp
:object_hook is an optional function that will be called with the result of any object literal decoded (a dict). The return value of object_hook will be used instead of the dict. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting).object_pairs_hook
是一个可选的函数,它会被调用于每一个有序列表对解码出的对象字面量。object_pairs_hook
的返回值将会取代原本的dict
。这一特性能够被用于实现自定义解码器。如果object_hook
也被定义,object_pairs_hook
优先。parse_float
,如果指定,将与每个要解码JSON
浮点数的字符串一同调用。默认状态下,相当于float(num_str)
。可以用于对JSON
浮点数使用其它数据类型和语法分析程序 (比如decimal.Decimal
)。parse_int
,如果指定,将与每个要解码JSON
整数的字符串一同调用。默认状态下,相当于int(num_str)
。可以用于对JSON
整数使用其它数据类型和语法分析程序 (比如float
)。parse_constant
,如果指定,将要与以下字符串中的一个一同调用:'-Infinity'
,'Infinity'
,'NaN'
。如果遇到无效的JSON
数字则可以使用它引发异常。- 要使用自定义的
JSONDecoder
子类,用cls
指定他;否则使用JSONDecoder
。额外的关键词参数会通过类的构造函数传递。
5.4.3.2.2 json.loads
json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
使用这个转换表 将 s
(一个包含 JSON
文档的 str
, bytes
或 bytearray
实例) 反序列化为 Python
对象。
5.4.3.2.3 json.dump
json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
使用这个转换表 将 obj
序列化为 JSON
格式化流形式的 fp
(支持 .write()
的 file-like object
)。json
模块始终产生 str
对象而非 bytes
对象。因此,fp.write()
必须支持 str
输入。
- 如果
skipkeys
是true
(默认为False
),那么那些不是基本对象(包括str
,int
、float
、bool
、None
)的字典的键会被跳过;否则引发一个TypeError
。 - 如果
ensure_ascii
是true
(即默认值),输出保证将所有输入的非ASCII
字符转义。如果ensure_ascii
是false
,这些字符会原样输出。 - If check_circular is false (default: True), then the circular reference check for container types will be skipped and a circular reference will result in a RecursionError (or worse).
- 如果
allow_nan
是false
(默认为 True),那么在对严格JSON
规格范围外的float
类型值(nan
、inf
和-inf
)进行序列化时会引发一个ValueError
。如果allow_nan
是true
,则使用它们的JavaScript
等价形式(NaN
、Infinity
和-Infinity
)。 - 如果
indent
是一个非负整数或者字符串,那么JSON
数组元素和对象成员会被美化输出为该值指定的缩进等级。 如果缩进等级为零、负数或者 “”,则只会添加换行符。None (默认值)
选择最紧凑的表达。 使用一个正整数会让每一层缩进同样数量的空格。 如果indent
是一个字符串 (比如"\t"
),那个字符串会被用于缩进每一层。 - 当被指定时,
separators
应当是一个(item_separator, key_separator)
元组。当indent
为None
时,默认值取(', ', ': ')
,否则取(',', ': ')
。为了得到最紧凑的JSON
表达式,你应该指定其为(',', ':')
以消除空白字符。 - 当
default
被指定时,其应该是一个函数,每当某个对象无法被序列化时它会被调用。它应该返回该对象的一个可以被JSON
编码的版本或者引发一个TypeError
。如果没有被指定,则会直接引发TypeError
。 - 如果
sort_keys
是true
(默认为False
),那么字典的输出会以键的顺序排序。 - 为了使用一个自定义的 JSONEncoder 子类(比如:覆盖了 default() 方法来序列化额外的类型), 通过
cls
关键字参数来指定;否则将使用JSONEncoder
。
5.4.3.2.4 json.dumps
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
使用这个转换表 将 obj
序列化为 JSON
格式的 str
。 其参数的含义与 dump()
中的相同。
5.4.3.3 案例
import json
with open('movies.json', mode='r', encoding='utf8') as fp:
json_data = json.load(fp)
for movie in json_data["movies"]:
print(movie)
print("*"*12)
json_str = json.dumps(json_data["movies"][-1])
print(json_str)
print("*"*12)
json_loads = json.loads(json_str)
print(type(json_loads), json_loads)
{'name': 'The Shawshank Redemption', 'rating': 9.7, 'category': [6, 9], 'showed': True}
{'name': 'Forrest Gump', 'rating': 9.5, 'category': [2, 9], 'showed': True}
{'name': 'Titanic', 'rating': None, 'category': [2, 9], 'show': False}
************
{"name": "Titanic", "rating": null, "category": [2, 9], "show": false}
************
<class 'dict'> {'name': 'Titanic', 'rating': None, 'category': [2, 9], 'show': False}