Python 系统、IO、序列化
注意,python中各种相对路径都相对于项目的工作目录,默认情况下即为项目的启动目录
读写文件
读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。
- 默认以
encoding='utf-8'
打开文件 -
errors
可以设为ignore
忽略或设为replace
通过namereplace
指定字符替换不支持的转码 -
.seek(0)
移动指针到头部 -
r
读取r+
读写 指针在头部 -
w
写入w+
读写 指针在尾部 -
a
追加写入a+
追加读写 指针在尾部 -
x
创建写入(文件已存在则报错)
f = open('/Users/michael/test.txt', 'w+', encoding='utf-16', errors='replace')
f.write("hello")
f.seek(0)
print(f.read())
当我们写文件时,操作系统可能会放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()
方法时,操作系统才保证把没有写入的数据全部写入磁盘。
由于文件读写时都有可能产生IOError,一旦出错,后面的close
就不会调用,应保证无论是否出错都能正确地关闭文件:
try:
f = open('/path/to/file', 'r')
print(f.read())
except BaseException as err:
print(err)
finally:
if f:
f.close()
或使用with
语句无论是否出错都会自动调用close()方法:
with open('/path/to/file', 'r') as f:
print(f.read())
从当前指针处向后读
调用read
会一次性读取文件的全部内容(但如内容过多会超出内存)
调用read(size)
方法,每次最多读取size个字节
调用readline()
每次读取一行
调用readlines()
一次读取所有内容并按行返回list
for line in f.readlines():
print(line.strip()) # 把末尾的'\n'删掉
二进制文件
要读取二进制文件,比如图片、视频、文件等,用带b
的模式打开或输入即可:
with open(fileName, 'wb') as activeFile:
for chunk in res.iter_content(len(res.content)):
activeFile.write(chunk)
内存中读写
在内存中创建的file-like Object,常用作临时缓冲。
通过getvalue
可以获取到完整内容(无视指针位置)
write
写入的内容可以互相叠加,但会覆盖初始化时的内容
StringIO
读写str
from io import StringIO
f = StringIO('A')
f.write('B')
f.write('C')
print(f.getvalue())#BC
BytesIO
读写bytes
from io import BytesIO
f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
print(f.getvalue())#b'\xe4\xb8\xad\xe6\x96\x87'
f.seek(0)
print(f.read())#b'\xe4\xb8\xad\xe6\x96\x87'
OS
查看操作系统信息
import os
>>>os.name
Linux/Unix/Mac为posix,Windows为nt。
>>>os.environ
查看系统环境变量
路径操作
-
os.chdir(path)
改变工作目录 -
os.path.abspath(path)
传入绝对/相对路径并返回绝对路径,如传入.
则返回当前项目工作目录的绝对路径,传入__file__
则返回该代码所在文件的绝对路径 -
os.path.dirname(path)
传入文件路径,获取其所在目录的绝对路径 -
os.listdir(path)
传入目录路径,返回目录下所有文件/目录名的list -
os.path.isdir(path) 和 os.path.isfile(path)
判断是否为目录/文件 -
os.walk(path)
可以创建一个生成器,用以遍历该目录及其所有后代目录下的所有文件- root 所指的是当前正在遍历的目录的自身地址
- dirs 是一个 list ,内容是当前正在遍历的目录中所有子目录的名字(不深入查找)
- files 同样是 list , 内容是当前正在遍历的目录中所有的文件(不深入查找)
for root, dirs, files in os.walk(path):
pass
以下方法只是字符串处理,不管是否真存在该路径
- os.path.join(path1,path2,...)
可传入多个路径进行拼接,Linux/Unix/Mac使用/
,Windows使用\
作为分隔符
import os
os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
- os.path.split(path)
将文件路径拆分为目录和文件名组成的元组 - os.path.splitext(path)
将文件路径拆分为目录+不带扩展的文件名和扩展名组成的元组
os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')
新增/删除/改名
# 创建目录
os.mkdir('/Users/testdir')
os.makedirs('/Users/testdir/a/b/c')#创建多级目录
# 删除空目录
os.rmdir('/Users/testdir/a/b/c')
os.removedirs('/Users/a/b/c')#删除多级空目录
# 重命名目录/文件:
os.rename('test.txt', 'test.py')
# 删除文件:
os.remove('test.py')
file-like Object
拥有read
方法的对象均可视为file-like Object,如open
打开的文件、StringIO
对象、BytesIO
对象、满足条件的自定义对象
class FLO():
content = ""
def read(self):
return self.content
def write(self, e):
self.content += e
序列化
我们把变量从内存中变成可存储或传输的过程称之为序列化,序列化之后的内容才可以写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
pickle
pickle模块只能用于Python,并且可能不同版本的Python彼此都不兼容,因此不推荐使用
json
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
"string" | str |
1234.56 | int或float |
true/false | True/False |
null | None |
通过json.dumps
可将以上Python类型转为json字符串并返回,或通过json.dump
将其写入一个 file-like Object。
import json
d = dict(name='Bob', age=20, score=88)
myJson = json.dumps(d)
print(myJson)#{"name": "Bob", "age": 20, "score": 88}
with open("1.txt", "w+") as f:
json.dump(d, f)
f.seek(0)
print(f.read())#{"name": "Bob", "age": 20, "score": 88}
class FLO():
content = ""
def read(self):
return self.content
def write(self, e):
self.content += e
flo = FLO()
json.dump(d, flo)
print(flo.read())#{"name": "Bob", "age": 20, "score": 88}
通过json.loads
把JSON反序列化为Python对象并返回,或通过json.load
从file-like Object中读取字符串并反序列化:
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
print(json.loads(json_str))#{"name": "Bob", "age": 20, "score": 88}
with open("1.txt", "r") as f:
print(json.load(f))#{"name": "Bob", "age": 20, "score": 88}
class FLO():
content = ""
def read(self):
return self.content
def write(self, e):
self.content += e
flo = FLO()
flo.content = '{"name": "Bob", "age": 20, "score": 88}'
print(json.load(flo))#{"name": "Bob", "age": 20, "score": 88}
对于不包含在上述列表中的对象(如自定义类的实例),可以在序列化时配置default
或在反序列化时配置object_hook
,先转化为dict
再通过该配置的函数转化为目标
json.dumps(s, default=lambda obj: obj.__dict__)