python学习(九)IO编程

  • 涉及数据交换,通常是磁盘、网络等,就需要IO接口。
  • IO编程中,Stream(流)是一个很重要的概念。
  • CPU和内存的速度远高于外设速度,在IO编程中,存在速度严重不匹配的问题。
  • 同步IO:程序暂停执行后续代码,等数据写入磁盘,再往下执行。
  • 异步IO:CPU不等待,后续代码立刻接着执行。回调模式,轮询模式。

文件读写

  • 读写文件:请求操作系统打开一个文件对象(通常称为文件描述符)
  • 通过操作系统提供的接口从这个文件对象中读取/写入数据(读/写文件)。

读文件

  • 内置open(),传入文件名和标示符。文件不存在,会抛出一个IOError的错误。
  • 调用read()方法可一次读取文件全部内容,把内容读到内存,用一个str对象表示。
  • 调用close()方法关闭文件。
  • 文件使用完毕后必须关闭,占用操作系统资源,且同一时间打开数量有限。
  • with语句自动调用close()方法
with open('/path/to/file', 'r') as f:
    print(f.read())
  • 文件很小:read()一次性读取最方便;不能确定文件大小:反复调用read(size)比较保险。
  • readline()每次读取一行内容。
  • 配置文件,调用readlines()一次读取所有内容并按行返回list

file-like Object

  • open()返回有read()方法的对象,统称为file-like Object
  • 可以是内存的字节流,网络流,自定义流等;不要求从特定类继承,只要写个read()方法。
  • StringIO:在内存中创建的file-like Object,常用作临时缓冲。

二进制文件

  • 'rb'模式打开文件。

字符编码

  • 读取非UTF-8编码的文本文件,需要给open()传入encoding参数。
  • 有些编码不规范文件可能会UnicodeDecodeError,文本文件中可能夹杂一些非法编码字符。
  • open()接收errors参数,如遇到编码错误后可直接忽略。errors='ignore'

写文件

  • 标识符'w'或者'wb',写文本文件或写二进制文件。
  • 调用write()方法来写入文件,调用close()方法来关闭文件。
  • 'w'模式写入文件时,如果文件已存在,会直接覆盖;'a'以追加(append)模式写入。

StringIO和BytesIO

  • StringIO:在内存中读写str
# 创建一个StringIO
from io import StringIO
f = StringIO()
f.write('hello')
f.write(' ')
f.write('world!')
# getvalue()方法用于获得写入后的str
print(f.getvalue()) # hello world!

# 可以用一个str初始化StringIO
from io import StringIO
f = StringIO('Hello!\nHi!\nGoodbye!')
while True:
    s = f.readline()
    if s == '':
        break
    print(s.strip())

BytesIO

  • 要操作二进制数据,需要使用BytesIO

操作文件和目录

  • 内置os模块直接调用操作系统提供的接口函数。
import os
os.name # 操作系统类型
# 'posix':系统是Linux、Unix或Mac OS X;'nt':Windows系统
# 获取详细的系统信息
os.uname()
# uname()Windows不提供

环境变量

  • 操作系统中定义的环境变量,全部保存在os.environ这个变量
  • 要获取某个环境变量的值,可以调用os.environ.get('key')

操作文件和目录

# 操作文件和目录的函数一部分在os模块,一部分在os.path模块
import os
# 查看、创建和删除目录
# 查看当前目录的绝对路径:
os.path.abspath('.') # '/Users/michael'
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
os.path.join('/Users/michael', 'testdir') # '/Users/michael/testdir'
# 然后创建一个目录:
os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
os.rmdir('/Users/michael/testdir')
# 合成路径时,不要直接拼字符串,通过os.path.join(),可正确处理不同操作系统的路径分隔符。
# 拆分路径时,不要直接拆字符串,通过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')
# 列出当前目录下的所有目录
[x for x in os.listdir('.') if os.path.isdir(x)]
# 列出所有的.py文件
[x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
  • shutil模块提供了copyfile()的函数

序列化

  • 把变量从内存中变成可存储或传输的过程称之为序列化。pickling
  • 把变量内容从序列化的对象重新读到内存里称之为反序列化。unpickling
  • pickle模块来实现序列化。
# 把一个对象序列化并写入文件
import pickle
d = dict(name='Bob', age=20, score=88)
pickle.dumps(d) # b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\...'
# 对象序列化后写入一个file-like Object
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不仅是标准格式,且比XML更快,而且可以直接在Web页面中读取。
JSON类型Python类型
{}dict
[]list
"string"str
1234.56int或float
true/falseTrue/False
nullNone
  • 内置json模块提供Python对象到JSON格式的转换。
import json
d = dict(name='Bob', age=20, score=88)
json.dumps(d) # '{"age": 20, "score": 88, "name": "Bob"}'
  • 把JSON反序列化为Python对象。
  • loads()把JSON的字符串反序列化。
  • load()方法从file-like Object中读取字符串并反序列化。
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
json.loads(json_str) # {'age': 20, 'score': 88, 'name': 'Bob'}

JSON进阶

  • dumps()方法参数列表,第一个必须的obj参数,还提供了可选参数,定制JSON序列化。
  • 可选参数default把任意一个对象变成一个可序列为JSON的对象。
# default可把任意一个对象变成一个可序列为JSON的对象。
# 为Student专门写一个转换函数,再把函数传进去。
def student2dict(std):
    return {
        'name': std.name,
        'age': std.age,
        'score': std.score
    }
# Student实例首先被student2dict()函数转换成dict,然后再被顺利序列化为JSON
print(json.dumps(s, default=student2dict)) # {"age": 20, "name": "Bob", "score": 88}
  • 可把任意class的实例变为dict__dict__属性
# 把任意class的实例变为dict
print(json.dumps(s, default=lambda obj: obj.__dict__))
# 通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。
# 少数例外,比如定义了__slots__的class。
  • JSON反序列化为一个对象实例
  • loads()方法转换出一个dict对象,传入object_hook函数把dict转换为实例
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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值