Open ShannonChenCHN opened 6 years ago
在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
f.close()
就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally
来实现。try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()
每次都这么写实在太繁琐,所以,Python引入了with
语句来自动帮我们调用close()
方法:
with open('/path/to/file', 'r') as f:
print(f.read())
几个常用方法:
read()
read(size)
readline()
readlines()
写文件和读文件是一样的,唯一区别是调用 open()
函数时,传入标识符'w'
或者'wb'
表示写文本文件或写二进制文件。
跟读文件一样,你可以反复调用write()
来写入文件,但是务必要调用 f.close()
来关闭文件,否则有可能导致没有把要保存的数据全部写入文件。
try:
f = open('/Users/michael/test.txt', 'w')
f.write('Hello, world!')
finally:
if f:
f.close()
写文件时也可以使用更保险、更简洁的 with
语句:
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
以 'w'
模式写入文件时,如果文件已存在,会直接覆盖(相当于删掉后新写入一个文件)。如果我们希望追加到文件末尾,可以传入'a'
以追加(append)模式写入。
像open()
函数返回的这种有个read()
方法的对象,在Python中统称为 file-like Object。除了file外,还可以是内存的字节流,网络流,自定义流等等。file-like Object不要求从特定类继承,只要写个read()
方法就行。
StringIO 就是在内存中创建的 file-like Object,常用作临时缓冲。
在内存中读写 str 时,用 StringIO。 在内存中读写 bytes 时,用 BytesIO。
读写 str:
from io import StringIO
f = StringIO()
f.write('hello\n')
f.write('Hi!\n')
f.write('world!')
print(f.getvalue())
读写 bytes:
from io import BytesIO
f = BytesIO()
f.write('中文'.encode('utf-8'))
print(f.getvalue())
如果我们要操作文件、目录,可以在命令行下面输入操作系统提供的各种命令来完成。比如dir、cp等命令。
如果要在Python程序中执行这些目录和文件的操作怎么办?其实操作系统提供的命令只是简单地调用了操作系统提供的接口函数,Python内置的os模块也可以直接调用操作系统提供的接口函数。
查看操作系统相关信息:
print(os.name)
print(os.uname())
查看环境变量:
# 查看当前目录的绝对路径
abspath = os.path.abspath('.')
print(abspath)
注:把两个路径合成一个时,不要直接拼字符串,而要通过 os.path.join()
函数,这样可以正确处理不同操作系统的路径分隔符。
# 查看当前目录的绝对路径
abspath = os.path.abspath('.')
print(abspath)
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来
# 这里不能用 home dir 的符号 ~
joinedpath = os.path.join(abspath, 'testdir')
print(joinedpath)
# 用户目录
homedir = os.path.expanduser('~')
print(homedir)
# 判断目录是否存在
if os.path.exists(joinedpath):
os.rmdir(joinedpath) # 删掉一个目录
# 创建一个目录
os.mkdir(joinedpath)
# 重命
newpath = joinedpath + 'new'
os.rename(joinedpath, newpath)
# 删掉一个目录
os.rmdir(newpath)
# 拆分路径
print(os.path.split('/Users/michael/testdir/file.txt'))
# 扩展名
print(os.path.splitext('/path/to/file.txt'))
注:
os
模块没有提供文件复制的功能,不过 shutil
模块提供了 copyfile()
的函数可供复制。# 复制
import shutil
licensepath = '../../LICENSE'
copypath = licensepath + 'new'
shutil.copy(licensepath, copypath)
# 删除
os.remove(copypath)
# 查看当前目录下的文件列表
print([x for x in os.listdir('.') if os.path.isdir(x)])
print([x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1] == '.py'])
序列化(pickling),又叫 serialization,是指把变量从内存中变成可存储或传输的数据的过程。 反过来,把序列化的数据重新转成内存里的变量内容称之为反序列化(unpickling)。
Python提供了pickle模块来实现序列化。
import pickle, os
# 序列化
d = dict(name='Bob', age=20, score=88)
print(pickle.dumps(d))
# 写入文件
filepath = 'dump.txt'
f = open(filepath, 'wb')
pickle.dump(d, f)
f.close()
# 读取文件,反序列化
readfile = open(filepath, 'rb')
d = pickle.load(readfile)
print(d)
readfile.close()
os.remove(filepath)
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON(JavaScript Object Notation),因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON标准规定JSON编码是UTF-8。
JSON和Python内置的数据类型对应如下:
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
"string" | str |
1234.56 | int或float |
true/false | True/False |
null | None |
# 序列化
print(json.dumps(d))
# 反序列化
json_str = '{"name": "Bob", "age": 20, "score": 88}'
result_dict = json.loads(json_str)
print(result_dict)
本质:JSON 的序列化本质上是 JSON 字符串与 Python dict 之间的相互转换。
import json
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
s = Student('Bob', 21, 89)
print(json.dumps(s, default=lambda obj: obj.__dict__))
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
print(json.loads(json_str, object_hook=dict2student))
注:定义了 __slot__
方法的 class 是拿不到 __dict__
属性的。
参考