1.读写文本数据
对文本数据进行读写操作,可能涉及到多种编码
解决:用 open() 配合 rt 模式
with open('somefile.txt','rt') as f:
data=f.read()
读写操作 open( ) wt 模式
wt 模式:如果文件已存在,会清除原先内容
书 P144
2.将输出重定向到文件
将print函数加上file参数即可:
with open('somefile.text','rt') as f:
print('ssss',file=f)
#确保文件是文本模式打开的,二进制的话会失败
3.以不同分隔符或行结尾符完成打印
print函数使用 sep 和 end 关键字参数
print('asas',50,23,sep=',')
print('das',2312,222,end='!!\n')
str.join()
print(','.join('acme',50,912))
#即将,插入进去
4.读写二进制数据
二进制数据如图像、声音
open() rb wb参数
with open('somefile.bin','rb') as f:
data = f.read()
读写二进制文件,要确保编码和解码操作
with open('some.txt','rb') as f:
data = f.read(16)
text = data.decode('utf-8')
with open('some.txt','rb') as f:
text = 'hello world'
f.write(text.encode('utf-8'))
想数组和c结构体这样的对象可以直接用来进行写操作:
import array
nums = array.array('i',[1,2,3,4])
with open('data.bin','wb') as f:
f.write(nums)
5.对已不存在的文件执行写入
open()函数 的 x模式替代 w模式
with open('somefile','wt') as f:
f.write('Hello\n')
with open('somefile','xt') as f:
f.write('Hello\n')
或者先检查文件是否存在:
import os
if not os.path.exists('somefile'):
with open('somefile','wt') as f:
f.write('Hello\n')
else:
print('File already exists!')
6.在字符串上执行I/O操作
我们想将一段文本或二进制字符串写入类似文件的对象上
io.StringIO() io.BytesIO()
import io
s = io.StringIO()
s.write('Hello world\n')
12
s.getvalue()
'Hello world\n'
print('This is a text\n',file=s)
s.getvalue()
'Hello world\nThis is a text\n\n'
如果是二进制数据,要用ByteIo
f = io.BytesIO()
f.write(b'binary data')
11
f.getvalue()
b'binary data'
7.读写压缩的数据文件
如 gzip \ bz2 格式
gizp模块 bz2模块
import gzip
with gzip.open('somefile.gz','rt') as f:
text = f.read()
cookbook P 151
8.对固定大小的记录进行迭代
iter() functools.partial()
from functools import partial
RECORD_SIZE = 32
with open('somefile.data','rb') as f:
records = iter(partial(f.read,RECORD_SZIE),b'')
for r in records:
...
附录A:Python的functools模块
partial
用于创建一个偏函数,将默认参数包装一个可调用对象,返回结果也是可调用对象。
偏函数可以固定住原函数的部分参数,从而在调用时更简单。
from functools import partial
int2 = partial(int, base=8)
print(int2('123'))
# 83
12345
update_wrapper
使用
partial
包装的函数是没有__name__
和__doc__
属性的。
update_wrapper
作用:将被包装函数的__name__
等属性,拷贝到新的函数中去。
from functools import update_wrapper
def wrap2(func):
def inner(*args):
return func(*args)
return update_wrapper(inner, func)
@wrap2
def demo():
print('hello world')
print(demo.__name__)
# demo
123456789101112
wraps
warps
函数是为了在装饰器拷贝被装饰函数的__name__
。
就是在update_wrapper
上进行一个包装
from functools import wraps
def wrap1(func):
@wraps(func) # 去掉就会返回inner
def inner(*args):
print(func.__name__)
return func(*args)
return inner
@wrap1
def demo():
print('hello world')
print(demo.__name__)
# demo
1234567891011121314
reduce
在 Python2 中等同于内建函数 reduce
函数的作用是将一个序列归纳为一个输出
reduce(function, sequence, startValue)
from functools import reduce
l = range(1,50)
print(reduce(lambda x,y:x+y, l))
# 1225
12345
cmp_to_key
在 list.sort 和 内建函数 sorted 中都有一个 key 参数
x = ['hello','worl','ni']
x.sort(key=len)
print(x)
# ['ni', 'worl', 'hello']
1234
- Python3 之前还提供了
cmp
参数来比较两个元素 cmp_to_key
函数就是用来将老式的比较函数转化为 key 函数
lru_cache
允许我们将一个函数的返回值快速地缓存或取消缓存。
该装饰器用于缓存函数的调用结果,对于需要多次调用的函数,而且每次调用参数都相同,则可以用该装饰器缓存调用结果,从而加快程序运行。
该装饰器会将不同的调用结果缓存在内存中,因此需要注意内存占用问题。
from functools import lru_cache
@lru_cache(maxsize=30) # maxsize参数告诉lru_cache缓存最近多少个返回值
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print([fib(n) for n in range(10)])
fib.cache_clear() # 清空缓存
12345678
9.将二进制数据读取到可变缓冲区
readinto()
import os.path
def read_into_buffer(filename):
buf = bytearray(os.path.getsize(filename))
with open(filename,'rb') as f:
f.readinto(buf)
retirn buf
#下面是用法
with open('sample.bin','wb') as f:
... f.write(b'Hello world')
...
buf = read_into_buffer('sample.bin')
buf
bytearray(b'Hello world')
10.对二进制文件做内存映射
将一个二进制文件加载到可变的字节数组中
mmap模块
Python 3.7.9 (default, Aug 31 2020, 17:10:11) [MSC v.1916 64 bit (AMD64)] on win32
import os
... import mmap
...
... def memory_map(filename ,access=mmap.ACCESS_WRITE):
... size = os.path.getsize(filename)
... fd = os.open(filename, os.O_RDWR)
... return mmap.mmap(fd, size, access=access)
...
...
size=100000
with open('sample.bin','wb') as f:
... f.seek(size-1)
... f.write(b'\x00')
...
这个不懂 书P155
11.处理路径名
os.path的函数
import os
path ='D:\pycharmProjects\data_sample.csv'
os.path.basename(path)
'data_sample.csv'
os.path.dirname(path)
'D:\\pycharmProjects'
12.检测文件是否存在
os.path.exists(’’)
返回ture 和false
>>>os.path.getsize(path)
87
>>>os.path.getmtime(path)
1608446350.6606245
>>>os.path.islink(path)
False
>>>os.path.isdir(path)
False
>>>os.path.realpath(path)
'D:\\pycharmProjects\\data_sample.csv'
13.获取目录内容的列表
os.listdir()
将得到原始目录文件列表
>>>names = os.listdir('D:\pycharmProjects')
>>>names
['.idea', '1.py', 'bi_load.py', 'data_sample.csv', 'error_check.py', 'heap.py', 'homework_03', 'homework_04', 'iteration.py', 'iter_text.py', 'main.py', 'main2.py', 'maxprofit.py', 'maxSubList.py', 'sample.bin', 'simple_bpNN', 'somefile.txt', 'venv', '__pycache__']
endswith 和 startswith 也可使用
>>>dirnames =[name for name in os.listdir('D:\pycharmProjects') if name.endswith('.py')]
>>>dirnames
['1.py', 'bi_load.py', 'error_check.py', 'heap.py', 'iteration.py', 'iter_text.py', 'main.py', 'main2.py', 'maxprofit.py', 'maxSubList.py']
至于文件名的匹配,可以用到glob 和 fnmatch模块
>>>import glob
>>>pyfiles = glob.glob('D:\pycharmProjects\*.py')
>>>pyfiles
['D:\\pycharmProjects\\1.py', 'D:\\pycharmProjects\\bi_load.py', 'D:\\pycharmProjects\\error_check.py', 'D:\\pycharmProjects\\heap.py', 'D:\\pycharmProjects\\iteration.py', 'D:\\pycharmProjects\\iter_text.py', 'D:\\pycharmProjects\\main.py', 'D:\\pycharmProjects\\main2.py', 'D:\\pycharmProjects\\maxprofit.py', 'D:\\pycharmProjects\\maxSubList.py']
>>>from fnmatch import fnmatch
>>>pyfiles = [name for name in os.listdir('') if fnmatch(name,'*.py')]
以上只是得到目录列表的条目名称,如果想要得到如 文件大小,修改日期等,可用os.path 模块或 os.stat()函数
>>>pyfiles = glob.glob('*.py')
>>>name_sz_date =[(name, os.path.getsize(name), os.path.getmtime(name)) for name in pyfiles]
>>>for name, size, mtime in name_sz_date:
... print(name, size, mtime)
...
1.py 358 1606379370.7863636
bi_load.py 205 1608445939.1266453
error_check.py 339 1607431357.4926434
heap.py 0 1607251664.313212
iteration.py 379 1606723461.9875746
iter_text.py 428 1606550544.0579054
main.py 325 1606550350.4782178
main2.py 259 1606723479.0354326
maxprofit.py 501 1607045771.2621334
maxSubList.py 447 1608300845.34697
14.绕过文件命编码
默认情况下,所有文件名都会根据 sys.getfilesystemencoding() 返回的文本编码形式进行编码和解码
>>>import sys
>>>sys.getfilesystemencoding()
'utf-8'
如果基于某些原因想忽略这种编码,可以使用原始字节串来指定文件名
15.打印无法解决的文件名
出现异常UnicodeEncodeError,并伴随 “surrogates not allowed”
可以用以下方式避免出现错误:
def bad_filename(filename):
return repr(filename)[1:-1]
try:
print(filename)
except UnicodeEncodeError:
print(bad_filename(filename))
16.为已经打开的文件修改或添加编码方式
io.TextIOWrapper()
使用io.TextIOWrapper 将其包装
import urllib.request
import io
u = urllib.request.urlopen('http:\\www.python.org')
f = io.TextIOWrapper(u,encoding='utf-8')
text = f.read()
如果想修改一个已经以文本模式打开的编码方式,可以在用新的编码替换之前的编码前,用detach()方法将已有的文件编码层移除
>>>import sys
>>>sys.stdout.encoding
'UTF-8'
>>>sys.stdout = io.TextIOWrapper(sys.stdout.detach(),encoding='lating-1')
>>>sys.stdout.encoding
'lating-1'
17.将字节数据写入文本文件
只需要简单地将字节数据写入文件底层的buffer中,如下:
>>>import sys
>>>sys.stdout.write(b'Hello\n')
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: write() argument must be str, not bytes
>>>sys.stdout.buffer.write(b'Hello\n')
Hello
6
也可以通过buffer属性读取文件二进制数据
I/O系统 是以不同的层次来构建的,文本文件是通过在缓冲的二进制模式文件之上添加一个Unicode编码、解码层来构建的。buffer属性简单地指向底层的文件。如果访问该属性,就可以绕过文本编码/解码层了。
18.将已有的文件描述符包装为文件对象
文件描述符只是一个由操作系统分配的整数句柄,用来指代某种系统I/O通道。如果刚好有这样一个文件描述符,就可以通过open()函数用python文件对象对其进行包装。
import os
fd = os.open('somefile.txt',os.O_WRONGLY | os.O_CREAT)
f = open(fd,'wt')
f.write('hello\n')
f.close()
高层的文件对象关闭或则销毁时,底层的文件描述符也会关闭,如果不想要,给open()提供可选参数即可。
f = open(fd, 'wt', closed=False)
P168
19.创建临时文件和目录
tempfile模块
from tempfile import TemporaryFile
with TemporaryFile('w+t') as f:
f.write('Hello World\n')
f.write('Testing\n')
f.seek(0)
data = f.read()
# 用完销毁
# 或者 f.TemporaryFile('w+t')
P170
20.同串口进行通信
通过串口读取和写入数据。
serial
P172
21.序列化python对象
我们需要将python对象序列化为字节流,这样就可以保存在文件中、存储到数据库或者网络连结传输
pickle 模块
import pickle
data = ... #Obeject
f = open('somefile','wb')
pickle.dump(data, f)
#要将对象转化为字符串,可以:
s = pickle.dumps(data)
#要从字节流重新创建出对象,可以使用pickle.load() 或者 pickle.loads()
f = open('somefile','rb')
data = pickle.load(f)
# from a string
data = pickle.loads()
如果需要处理多个对象,可以这么做
import pickle
f = open('somedata','wb')
pickle.dump([1,2,3,4], f)
pickle.dump('hello', f)
pickle.dump({'Apple','Rear'}, f)
f.close()
f = open('somedata','rb')
>>>pickle.load(f)
...
[1, 2, 3, 4]
>>>pickle.load(f)
hello
>>>pickle.load(f)
{'Apple','Rear'}