一、文件读写
1.1 读文件
(1)打开文件
使用Python内置的open()
函数,传入文件名和标示符,打开一个文件对象:
>>> import os
>>> f = open('/Users/michael/test.txt', 'r')
标示符'r'
表示读,这样,我们就成功地打开了一个文件。
Python引入了with
语句来避免程序出错:
with open('/path/to/file', 'r') as f:
print(f.read())
上面的代码相当于:
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()
(2)读文件内容
方法 | 作用 |
---|---|
read() | 一次读取文件的全部内容 |
read(size) | 每次最多读取size个字节的内容 |
readline() | 每次读取一行内容 |
readlines() | 一次读取所有内容并按行返回 |
(3)关闭文件
调用close()
方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源。
>>> f.close()
(4)读取其它编码格式文件
要读取二进制文件,比如图片、视频等等,用'rb'
模式打开文件即可:
>>> f = open('/Users/michael/test.jpg', 'rb')
>>> f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节
要读取非UTF-8编码的文本文件,需要给open()
函数传入encoding
参数,例如,读取GBK编码的文件:
>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
>>> f.read()
'测试'
1.2 写文件
调用open()
,传入标识符'w'
或者'wb'
表示写文本文件或写二进制文件:
>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()
可以反复调用write()
来写入文件,但是务必要调用f.close()
来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()
方法时,操作系统才保证把没有写入的数据全部写入磁盘。
所以通常,还是使用with
语句写文件:
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
二、文件和目录操作
Python内置的os
模块可以直接调用操作系统提供的接口函数。
2.1 目录操作
(1)查看目录
# 查看当前目录的绝对路径:
>>> os.path.abspath('.')
'/Users/michael'
(2)创建目录
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
# 然后创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
(3)删除目录
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')
(4)合并与拆分路径
把两个路径合成一个时,不要直接拼字符串,而要通过os.path.join()
函数。
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
要拆分路径时,也不要直接去拆字符串,而要通过os.path.split()
函数。
>>> os.path.split('/Users/michael/testdir/file.txt')
('/Users/michael/testdir', 'file.txt')
(5)获取扩展名
os.path.splitext()
可以直接让你得到文件扩展名:
>>> os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')
2.2 文件操作
(1)文件重命名
# 对文件重命名:
>>> os.rename('test.txt', 'test.py')
(2)文件删除
# 删掉文件:
>>> os.remove('test.py')
(3)复制与移动文件
os
模块中并未提供复制与移动文件的函数,但shutil
模块提供了copyfile()
的函数,可以看作是os
模块的补充。
shutil.copy(src_file, target_path)
shutil.move(src_file, target_path)
import shutil
shutil.copy('/Users/michael/testdir1/file.txt', '/Users/michael/testdir2')
shutil.move('/Users/michael/testdir1/file.txt', '/Users/michael/testdir2')
三、JSON
要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,最常用的就是序列化为JSON。
因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
3.1 Python dict -> JSON
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
。
3.2 JSON -> Python dict
要把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'}
3.3 Python Class -> JSON
由于通常情况下,我们会用class
表示对象,如果直接将对象序列化肯定会报错,原因是Student
对象不是一个可序列化为JSON的对象。
import json
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
s = Student('Bob', 20, 88)
print(json.dumps(s))
# 输出
Traceback (most recent call last):
...
TypeError: <__main__.Student object at 0x10603cc50> is not JSON serializable
但,dumps()
方法还提供了一大堆的可选参数,其中可选参数default
就支持通过提供转换函数,为dumps()
传入对象实例以及转换函数,就可以实现序列化。
精简后的写法如下:
print(json.dumps(s, default=lambda obj: obj.__dict__))
因为通常class
的实例都有一个__dict__
属性,它就是一个dict
,用来存储实例变量。
3.4 JSON -> Python Class
如果我们要把JSON反序列化为一个Student
对象实例,loads()
方法首先转换出一个dict
对象,然后,我们传入的object_hook
函数负责把dict
转换为Student
实例:
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> print(json.loads(json_str, object_hook=dict2student))
<__main__.Student object at 0x10cd3c190>