11.IO编程
本章IO编程都是同步IO
11.1文件读写
11.1.1读文件
>>> f = open('/Users/michael/test.txt', 'r') # r表示读,若不存在则抛出IOError
- 如果打开成功,则可以调用
read()
函数一次性读取全部文件内容,用一个str
对象表示
>>> f.read()
- 最后调用
close()
>>> f.close()
- 结合
try...catch
语句/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()
- 读取方法
read()
一次性读取全部内容并返回strread(size)
最多读取size个字节内容readline()
每次读取一行readlines()
一次读取全部内容并返回list
- e.g.
for line in f.readlines():
print(line.strip()) # 把末尾的'\n'删掉
11.1.2 file-like Object
-
open()函数返回的有个read()方法的对象,在Python中称file-like Object,还可以使用在字节流、网络流、自定义流 etc.
-
StringIO
就是在内存中创建的file-like Object,常用作临时缓冲
11.1.3二进制文件
>>> f = open('/Users/michael/test.jpg', 'rb') # 二进制文件使用rb
11.1.4字符编码
- 读取非UTF-8文件需要在open()函数中传入
encoding
参数(默认是UTF-8)
>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore') # 遇到编码错误可以忽略
11.1.5写文件
- open函数中使用
w
或wb
覆盖写入,使用a
追加到文件末尾
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
11.2 StringIO和BytesIO
11.2.1 StringIO
- 在内存中读写str,使用
getvalue()
可获取写入的str,其余操作同文件读写
>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
>>> print(f.getvalue())
hello
11.2.2 BytesIO
- 在内存中读写二进制文件、bytes
>>> from io import BytesIO
>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
>>> f.read()
b'\xe4\xb8\xad\xe6\x96\x87'
11.3操作文件和目录
- 使用内置的
os
模块 os.name
如果是posix
,说明系统是Linux
、Unix
或Mac OS X
,如果是nt
,就是Windows
系统
>>> import os
>>> os.name # 操作系统类型
'posix'
os.uname()
获取详细系统信息(在Windows上不提供)
>>> os.uname()
posix.uname_result(sysname='Darwin', nodename='MichaelMacPro.local', release='14.3.0', version='Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64', machine='x86_64')
os,environ
系统定义的环境变量
>>> os.environ
environ({'VERSIONER_PYTHON_PREFER_32_BIT': 'no', 'TERM_PROGRAM_VERSION': '326', 'LOGNAME': 'michael', 'USER': 'michael', 'PATH': '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin', ...})
>>> os.environ.get('PATH') # 获取某个环境变量的值
'/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin'
>>> os.environ.get('x', 'default')
'default'
操作文件和目录
-
一部分在
os
模块,一部分在os.path
中 -
查看、创建、删除目录
# 查看当前目录的绝对路径:
>>> os.path.abspath('.')
'/Users/michael'
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
# 然后创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')
- 拆分路径
split
>>> os.path.split('/Users/michael/testdir/file.txt')
('/Users/michael/testdir', 'file.txt')
- 获得文件拓展名
splitext
>>> os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')
- 重命名,删除文件
# 对文件重命名:
>>> os.rename('test.txt', 'test.py')
# 删掉文件:
>>> os.remove('test.py')
shutil
模块提供了copyfile()
的函数,你还可以在shutil
模块中找到很多实用函数,它们可以看做是os
模块的补充
shutil.move('/tmp/20170223/new','/tmp/20170223/test') # 移动文件, 重命名等
shutil.copytree('/tmp/20170223/','/tmp/20170223-2/') # 递归复制
shutil.rmtree('/tmp/20170223-2/') # 递归删除目录树
shutil.get_archive_formats() # 返回支持的 压缩格式列表, 如 [(name,desc),('tar','uncompressed tar file')],
shutil.copy('/tmp/20170223/new','/tmp/20170223/new2') # 复制文件及权限, Copy data and mode bits
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
shutil.copyfile('f1.log', 'f2.log') # 拷贝文件, Copy data from src to dst
shutil.copymode('f1.log', 'f2.log') # 仅拷贝权限,内容,用户,组不变, Copy mode bits from src to dst
shutil.copystat('f1.log', 'f2.log') # 仅拷贝状态信息, Copy all stat info (mode bits, atime, mtime, flags) from src to dst
shutil.copy2('f1.log', 'f2.log') # 拷贝文件和状态信息, Copy data and all stat info
- 过滤文件
>>> [x for x in os.listdir('.') if os.path.isdir(x)] # 过滤目录
['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Applications', 'Desktop', ...]
>>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py'] # 过滤文件
['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']
11.4序列化pickling
-
把变量从内存中变成可存储或传输的过程称之为序列化(pickling,同Java中的serialization)
-
pickle.dumps()
方法把任意对象序列化成一个bytes
,然后,就可以把这个bytes
写入文件
>>> import pickle
>>> d = dict(name='Bob', age=20, score=88)
>>> pickle.dumps(d)
b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'
pickle.dump()
直接把对象序列化后写入一个file-like Object:
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()
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更快,可在Web中读取
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
“string” | str |
1234.56 | int或float |
true/false | True/False |
null | None |
- 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"}'
-
dump()
方法可以直接把JSON写入一个file-like Object
-
把JSON反序列化为Python对象,用
loads()
或者对应的load()
方法
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}
- 序列化对象class,
- 序列化用
default
- 反序列化用
object_hook
- 序列化用
import json
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
def student2dict(std): # 将对象转为可序列化的JSON对象
return {
'name': std.name,
'age': std.age,
'score': std.score
}
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
# 序列化
>>> print(json.dumps(s, default=student2dict))
{"age": 20, "name": "Bob", "score": 88}
>>> print(json.dumps(s, default=lambda obj: obj.__dict__)) # 较快的方法
# 反序列化
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> print(json.loads(json_str, object_hook=dict2student))
<__main__.Student object at 0x10cd3c190>
参考教程
(转载整理自网络,如有侵权,联系本人删除,仅供技术总结使用)