2.2. 文件和IO

2.2.1. 读写文本数据

with open('./somefile.txt','r',encoding='utf-8',errors='ignore') as f:
    lines = f.readlines()
    print(lines)

2.2.2. 使用其他分隔符或行终止符打印

In [6]: print('ACME', 50, 91.5)
ACME 50 91.5

In [7]: print('ACME', 50, 91.5,sep=",",end="xxxx")
ACME,50,91.5xxxx

2.2.3. 读写字节数据

with open('./somefile.txt','rb') as f:

2.2.4. 字符串的I/O操作

In [9]: import io

In [10]: s = io.StringIO()

In [11]: s.write("abc")
Out[11]: 3

In [12]: s.write("abc")
Out[12]: 3

In [13]: s.getvalue()
Out[13]: 'abcabc'

2.2.5. 读写压缩文件

import gzip
with gzip.open('somefile.gz', 'rt') as f:
    text = f.read()

import bz2
with bz2.open('somefile.bz2', 'wt') as f:
    f.write(text)

2.2.6. 固定大小记录的文件迭代

from functools import partial

RECORD_SIZE = 32

with open('./somefile.txt', 'r',encoding='utf-8') as f:
    records = iter(partial(f.read, RECORD_SIZE), '')
    for r in records:
        pass

2.2.7. 读取二进制数据到可变缓冲区中

import os 
def read_into_buffer(filename):
    buf = bytearray(os.path.getsize(filename))
    with open(filename,'rb') as f:
        f.readinto(buf)
    return buf 

with open('sample.bin', 'wb') as f:
    f.write(b'Hello World')

buf = read_into_buffer('sample.bin')
print(buf)

2.2.8. 内存映射的二进制文件

为了随机访问文件的内容,使用 mmap 将文件映射到内存中是一个高效和优雅的方法。 例如,你无需打开一个文件并执行大量的 seek() , read() , write() 调用, 只需要简单的映射文件并使用切片操作访问数据即可。

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 = 1000000
with open('data', 'wb') as f:
    f.seek(size-1)
    f.write(b'\x00')

m = memory_map('data')
print(len(m))
print(m[0])
m[0:11] = b'Hello World'
m.close()

with open('data', 'rb') as f:
    print(f.read(11))

2.2.9. 文件路径名的操作

In [1]: import os

In [2]:  path = '/Users/beazley/Data/data.csv'

In [3]: os.path.basename(path)
Out[3]: 'data.csv'

In [4]: os.path.dirname(path)
Out[4]: '/Users/beazley/Data'

In [5]: os.path.join('/Users/beazley/Data//','a','data.csv')
Out[5]: '/Users/beazley/Data//a/data.csv'

In [6]: os.path.join('/Users/beazley/Data','a','data.csv')
Out[6]: '/Users/beazley/Data/a/data.csv'

In [7]: os.path.splitext(path)
Out[7]: ('/Users/beazley/Data/data', '.csv')

In [8]: os.path.split(path)
Out[8]: ('/Users/beazley/Data', 'data.csv')

In [9]: os.path.expanduser('~/a.txt')
Out[9]: '/Users/bytedance/a.txt'

2.2.10. 测试文件是否存在

使用 os.path.exists 来判定存在。

2.2.11. 获取文件夹中的文件列表

import os
dir = '.'
files = [ x for x in os.listdir() if os.path.isfile(os.path.join(dir, x))]
dirs = [x for x in os.listdir() if os.path.isdir(os.path.join(dir, x))]
print(files)
print(dirs)
pyfiles = [x for x in os.listdir() if os.path.isfile(x) and x.endswith('.py')]
print(pyfiles)

import glob
pyfiles = glob.glob('./*.py')
print('-'*20)
file_metadata = [(name, os.stat(name)) for name in pyfiles]
for name,meta in file_metadata:
    print(name,meta.st_size)

2.2.12. 增加或改变已打开文件的编码

>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='latin-1')
>>> sys.stdout.encoding
'latin-1'

2.2.13. 将字节写入文本文件

In [1]: import sys

In [2]: sys.stdout.write("abc")
Out[2]: abc3

In [3]: sys.stdout.buffer.write(b'abc')
abcOut[3]: 3

2.2.14. 将文件描述符包装成文件对象

import os
fd = os.open('somefile.txt', os.O_WRONLY | os.O_CREAT)

# Turn into a proper file
f = open(fd, 'wt')
f.write('hello world\n')
f.close()

2.2.15. 创建临时文件和文件夹

TemporaryFile() 、NamedTemporaryFile() 和 TemporaryDirectory() 函数 应该是处理临时文件目录的最简单的方式了,因为它们会自动处理所有的创建和清理步骤。 在一个更低的级别,你可以使用 mkstemp() 和 mkdtemp() 来创建临时文件和目录,函数 mkstemp() 仅仅就返回一个原始的OS文件描述符, 你需要自己将它转换为一个真正的文件对象。 同样你还需要自己清理这些文件。