文件读写
读写文件是最常见的IO操作。Python内置读写文件函数。
# 读文件 # 打开文件对象,以阅读文件的方式使用Python内置的open()函数,输入文件名和标记符: file = open('file_path', 'r') # 文件打开成功后,调用read()方法可以一次读取文件的全部内容,Python内容读到内存,用一个str对象表示 file.read() # 最后一步是调用close()关闭文件的方法。文件使用后必须关闭,因为文件对象占用了操作系统的资源,操作系统可以同时打开的文件数量有限 file.close() # 阅读文件可能会被打败IOError,需要使用以确保文件正常关闭try...except...finally包裹,并确保关闭 try: f = open('/path/to/file', 'r') print(f.read()) except(IOError): print("open fail") finally: if f: f.close() # 操作方便,Python引入了with自动帮助我们调用句子close()方法 with open('file_path', 'r') as f: print(f.read()) # 前面的try ... finally是一样的,但是代码更好更简单,不需要调用f.close()方法。 # read()一次性读取,read(size)每次读取指定大小的文件,readlines()每次读读一行,后两行需要多次阅读才能获得文件的所有内容
读二进制文件
# 读取图片、视频等二进制文件,使用‘rb模式打开文件 file = open('path/test.jpg', 'rb') file.read() # 和文件读取一样,需要处理异常 # 读取非UTF-8编码的文本文件需要提供open()函数传入encoding配置编码表的参数 file = open('path/test.txt', 'r', encoding='gbk') file.read()
写文件
# 写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件
""" 可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。 当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。 只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。 忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来操作 """
with open('path/test.txt', 'w') as file:
file.write('Hello, world!')
StringIO
内存缓冲区,StringIO和BytesIO读取内存数据
# 很多时候,数据读写不一定发生在磁盘上,也可以在内存中读写
# python提供了StringIO和BytesIO读取内存数据
# 写入内存
# 要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可。
from io import StringIO
f = StringIO()
f.write('hello')
f.write(' ')
f.write('world!')
print(f.getvalue())
''' hello world! '''
# getvalue()方法用于获得写入后的str。
hello world!
'\nhello world!\n'
# 内存读取
# 要读取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! '''
Hello!
Hi!
Goodbye!
'\nHello!\nHi!\nGoodbye!\n'
BytesIO
# StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。
# BytesIO用法和StringIO一样
# 写入内存
from io import BytesIO
f = BytesIO()
f.write('中文'.encode('utf-8'))
print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'
# 内存读取
from io import BytesIO
f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
f.read()
b'\xe4\xb8\xad\xe6\x96\x87'
文件对象
文件对象用于python对文件系统的操作
# Python内置的os模块也可以直接调用操作系统提供的接口函数。
# os.name变量用于判断操作系统的类型
import os
os.name # 操作系统类型
# 如果是posix,说明系统是Linux、Unix或Mac OS X,如果是nt,就是Windows系统。
'nt'
操作目录
# 操作文件和目录的函数一部分放在os模块中,一部分放在os.path模块中
# 查看、创建和删除目录如下:
# 查看当前目录的绝对路径:
os.path.abspath('.')
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
os.path.join('path', '文件名')
# 然后创建一个目录:
os.mkdir('path')
# 删掉一个目录:
os.rmdir('path')
两个路径合成一个时,不要直接拼字符串,而要通过os.path.join()函数,这样可以正确处理不同操作系统的路径分隔符。
# 在Linux/Unix/Mac下,路径以 / 连接
# 而Windows下路径以 \ 连接
拆分路径时,要通过os.path.split()函数,这样可以把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名
# 差分路径将文件与目录分开
os.path.split('/Users/michael/testdir/file.txt')
#('/Users/michael/testdir', 'file.txt')
os.path.splitext()可以直接让你得到文件扩展名
os.path.splitext('/path/to/file.txt')
#('/path/to/file', '.txt')
操作文件
#文件操作使用下面的函数:
# 对文件重命名:
os.rename('test.txt', 'test.py')
# 删掉文件:
os.remove('test.py')
序列化
# 在程序运行的过程中,所有的变量都是在内存中
# 一旦程序结束,变量所占用的内存就被操作系统全部回收。下次重新运行程序,变量又被初始化
# 把变量从内存中变成可存储或传输的过程称之为序列化
# 把变量内容从序列化的对象重新读到内存里称之为反序列化
# Python提供了pickle模块来实现序列化
# pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件。
# 或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object
import pickle
d = dict(name='Bob', age=20, score=88)
# pickle.dumps(d)
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
# 我们要把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象,
# 也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
d
#{'age': 20, 'score': 88, 'name': 'Bob'}
JSON
# 要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,
# 比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。
# JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
# Python内置的json模块提供了非常完善的Python对象到JSON格式的转换。
dict转json
# dumps()方法返回一个str,内容就是标准的JSON。类似的,dump()方法可以直接把JSON写入一个file-like Object。
import json
d = dict(name='Bob', age=20, score=88)
json.dumps(d)
#'{"age": 20, "score": 88, "name": "Bob"}'
'{"name": "Bob", "age": 20, "score": 88}'
# json字符串转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'}
{'age': 20, 'score': 88, 'name': 'Bob'}
# JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str与JSON的字符串之间转换
class转json
# Python的dict对象可以直接序列化为JSON的{},class的实例对象都无法直接序列化为JSON
# class实例化对象转化为dict后再转为json
class Student(object):
__name=None
__age=None
def __init__(self,name,age):
self.__name=name
self.__age=age
def getName(self):
return self.__name
def getAge(self):
return self.__age
def class_to_dict(object):
return {
'name':object.getName(),
'age':object.getAge()
}
student=Student('zhansna',20)
print(student)
student_to_dict=class_to_dict(student)
print(student_to_dict)
<__main__.Student object at 0x000001B5BC10A160>
{'name': 'zhansna', 'age': 20}
# 将类转化的dict再转化为json
student_to_json=json.dumps(student_to_dict)
print("转化前:",type(student_to_dict))
print(student_to_json)
print("转化后:",type(student_to_json))
转化前: <class 'dict'>
{"name": "zhansna", "age": 20}
转化后: <class 'str'>
# 为了减少变量的定义,json.dumps()方法有一个default参数定义class转化dict规则
student_json=json.dumps(Student("lihua",20),default=class_to_dict)
print(student_json)
{"name": "lihua", "age": 20}
# 但是这样对与每个class都要编写转化函数,class对象提供了一个__dict__变量用来存储实例变量
print(student.__dict__)
{'_Student__name': 'zhansna', '_Student__age': 20}
# 有了__dict__属性就可以直接转换
s1=Student("lisa",20)
student1_json=json.dumps(s1,default=lambda s:s.__dict__)
print(student1_json)
{"_Student__name": "lisa", "_Student__age": 20}
# JSON反序列化为一个Student对象实例,loads()方法首先转换出一个dict对象 # 再编写方法将dict转化为class # json模块的dumps()和loads()函数是定义得非常好的接口的典范。
自定义default转化规则就可以将任意类型转化为json