本文对使用python对多种格式的文件的写入与读取进行不完全总结。

Updated: 2022 / 12 / 20



多种格式文件的写入与读取 - 不完全总结

  • JSON
  • 写入
  • XLSX
  • 方法
  • openpyxl
  • 读取
  • openpyxl
  • 写入
  • openpyxl
  • 设置样式
  • 合并、拆分单元格
  • CSV
  • 写入
  • Pickle
  • 序列化方法
  • 反序列化方法
  • PDF
  • 方法
  • df.to_html
  • reportlab
  • word
  • 方法
  • python-docx
  • log, txt
  • 读取
  • 示例
  • 参考链接



JSON

写入

toFile = ./output.json 为目标路径,对如何写入json文件 12

  • f = open(file, mode, encoding='utf-8')
f = open(toFile, 'w', encoding='utf-8')      # w, write mode
f.write(toStr)                               # write 'toStr' 
f.close()
  • with open( , 'w', encoding='utf-8') as f
with open(file, 'w', encoding='utf-8') as f:
    f.write(toStr)
    f.close()

XLSX

方法

openpyxl

openpyxl 是一个用于处理 xlsx 格式 Excel 表格文件的第三方 python 库,其支持 Excel 表格绝大多数基本操作。

使用 pip 或通过专门 python IDE(如 pyCharm )进行安装。其中 pip 安装方法,命令行输入pip install openpyxl

方法

说明

load_workbook(filename)

使用此方法可对 xlsx 格式的文件进行内容读取,该方法中还有一个 read_only 参数用于设置文件打开方式,默认为可读可写,该方法最终将返回一个 workbook 的数据对象。


wb = openpyxl.load_workbook(‘example.xlsx’)文件必须是 xlsx 格式,如果是其他格式在执行前可利用 win32 辅助转化。在读取文件时需要加上参数 data_only=True,这样才能返回数字,否则将返回字符串,即公式本身。

wb.get_sheet_names(),获取所有工作表名(返回一个列表)

wb['Sheet2'],获取某一特定的工作表,比如名为 Sheet2 的工作表

wb['Sheet2'].title,获取指定工作表的表名

wb['Sheet2'].maxrow 3,获取指定工作表的总行数

wb['Sheet2'].max_column 3,获取指定工作表的总列数

wb.active,一般来说,表格大多数用到的是打开时显示的工作表,这时可以用active来获取当前工作表

获取指定单元格的几种方式如下:


wb['Sheet2']['A2'],获取指定工作表的指定单元格,此处表示名为 Sheet2 工作表的 A2 单元格

wb['Sheet2'].cell(1. 2),获取指定工作表的指定单元格,此处表示获取名为 Sheet2 工作表的第1行第2列,即B2,的单元格


获取单元格的值,使用 .valuewb['Sheet2]['A2'].value,获取名为 Sheet2 的工作表的 A2 单元格的值

wb['Sheet2'].cell(1, 2).value,获取名为 Sheet2 的工作表的 B1 单元格的值


获取单元格的行索引和列索引

wb['Sheet2'][‘A2’].columnwb['Sheet2']['A2].row

wb['Sheet2'].cell(1, 2).column, wb['Sheet2'].cell(1, 2).row


删除工作表

可以使用 workbook 对象的 remove(sheet) 方法删除。


需要注意地是,wb['Sheet2].cell(row, column) 中的参数分别是行和列,且必须为整数。如果列为英文字母,可以利用 openpyxl.utils 中的 column_index_from_string 进行字母数字的转化。顺便,也可以利用 get_column_letter(number) 进行数字字母间的转化。实例请查看 4

max_row, max_column

有时候我们还可能需要确定表格的大小,即获取表格行和列的最大值。


读取

openpyxl

在处理 Excel 表格有时可能需要对表格进行遍历查找,openpyxl 中便提供了一个行和列的生成器 sheet.rowssheet.columns, 这两个生成器里面是每一行(或列)的数据,每一行(或列)又由一个 tuple 包裹,借此可以很方便地完成对行和列的遍历:

for row in sheet.rows:
    for cell in row:
        print(cell.value)
        
for column in sheet.columns:
    for cell in column:
        print(cell.value

也可以通过 list(sheet.rows)index 对某一行或列进行遍历,而在此值得注意的是,由于sheet.rows ( 或 sheet.columns ) 是生成器类型,是不能直接调用的,需将其转化为一个 list 类型,然后再通过索引遍历,

for cell in list(sheet.rows)[0]:
    print(cell.value)

同时,也可以通过使用 sheet[行列值:行列值] 来对给定单元格范围进行遍历

for spaces in sheet['A1':'B2']:
    for cell in spaces:
        print(cell.value)



写入

openpyxl

参考这里 4

默认的打开方式为可读可写。使用 load_workbook(filename) 读取 Excel 文档后也就可以直接写入了,比如通过 sheet[行列值] 写入单元格或者传入 Excel 中的公式进行赋值,又或者使用 sheet.append(parameters) 进行一行或多行写入。

sheet['A1'].value = 2									# 直接赋值
sheet['A6'].value = '=SUM(A1:A5)'						# 公式赋值

row = [1 ,2, 3, 4, 5]									# 写入一行
sheet.append(row)

rows = [												# 写入多行
    ['ID', 'Name', 'Department'],
    ['001', 'Lee','CS'],
    ['002', 'John','MA'],
    ['003', 'Amy','IS']
]
sheet.append(rows)

另外,如果需要新建一个 Excel 文件,可以使用 Workbook() 方法,同时它会自动提供一个sheet 工作表。

wb = openpyxl.Workbook()								# 新建一个Excel文档
wb.remove(sheet)										# 删除某个工作表

写完文件后,使用 workbook.save(path+filename) 进行保存,不过要注意文件扩展名一定要是 xlsx 格式,

wb.save('new_file.xlsx')								# 保存文件至当前目录
设置样式

单元格样式主要包括 字体边框颜色 以及 对齐 方式等,这些均位于 openpyxl.styles 库中,

# 导入字体、边框、颜色以及对齐方式相关库
from openpyxl.styles import Font, Border, Side, PatternFill, colors, Alignment
  • 字体
    通过 sheet 单元格 font 属性设置字体风格
# 设置字体风格为Times New Roman,大小为16,粗体、斜体,颜色蓝色
sheet['A1'].font = Font(name='Times New Roman', size=16, bold=True, italic=True, color=colors.BLUE)
  • 对齐
    通过 sheet 单元格 alignment 属性设置文本对齐风格
# 通过参数horizontal和vertical来设置文字在单元格里的对齐方式,此外设置值还可为left和right
sheet['B1'].alignment = Alignment(horizontal='center',vertical='center')
  • 边框
    通过 sheet 单元格 border 属性设置字体风格
# 首先设置边框四个方向的线条种类
left, right, top, bottom = [Side(style='thin', color='000000')] * 4
# 再将各方向线条作为参数传入Border方法
sheet['C1'].border = Border(left=left, right=right, top=top, bottom=bottom)
  • 行高、列宽
    行和列的长度大小可以通过 row_dimensions[序号].heightcolumn_dimensions[标号].width 来设置
sheet.row_dimensions[1].height = 25					    # 设置行高
sheet.column_dimensions['D'].width = 15.5               # 设置列宽



合并、拆分单元格

对单元格的合并与拆分,主要是通过 sheetmerge_cells(args1:args2)unmerge_cells(args1:args2) 两个方法来实现的。

方法

说明

sheet.merge_cells('A1:B2')

合并单元格

sheet.unmerge_cells('A1:B2')

拆分单元格

当然,除了对角矩形区域化合并,也可以对一行或一列进行合并,只需相应修改参数即可。不过,这里要注意的是,合并后单元格显示的文本内容是合并前最左上角单元格的内容,而其他单元格内容则会自动清除。


CSV

多行写入 5


python2.x 中写入CSV时,CSV文件的创建必须加上 b 参数,即csv.writer(open('test.csv','wb')),不然会出现隔行的现象。

这是因为—— python 正常写入文件的时候,每行的结束默认添加 n,即 0x0D,而 writerow 命令的结束会再增加一个 0x0D0A ,因此对于 windows 系统来说,就是两行,而采用 b 参数,用二进制进行文件写入,系统默认是不添加 0x0D 的。

python3.x 中换成采用 newline='' 这一参数来达到这一目的。6



写入

./FILE.csv为目标路径,对如何写入csv文件 7

  • open(file, mode, encoding, newline, closefd).write(YourFileContent)

如果目标写入内容的类型为 <class 'bytes'>

FILE = open('./FILE.csv', 'wb').write(YourFileContent)FILE = open('./FILE.csv', 'w').write(YourFileContent) # TypeError: write() argument must be str, not bytes

如果目标写入内容的类型为 <class 'string'>

FILE = open('./FILE.csv', 'wb').write(YourFileContent) # TypeError: a bytes-like object is required, not 'str'FILE = open('./FILE.csv', 'w').write(YourFileContent)



Pickle

pickle 模块是以二进制的形式序列化后保存到文件中(保存文件的后缀为 .pkl ),不能直接打开进行预览 8

python 的另一个序列化标准模块 json,则是 human-readable 的,可以直接打开查看(例如在 notepad++ 中查看)。

举个例子,如下所示:
一个字典 a = {'name':'Tom','age':22},用 pickle.dump 存到本地文件,所存数据的结构就是字典,而普通的 file.write 写入文件的是字符串。

读取时,pickle.load 返回的是一个字典,file.read 返回的是一个字符串。得到的 b 的类型是字典,ba 是等价的,也就是说 pickle 可以把字典、列表等结构化数据存到本地文件,读取后返回的还是字典、列表等结构化数据。而 file.writefile.read 存取的对象是字符串。

import pickle

a = {'name':'Tom','age':22}

with open('text.txt','wb') as file:
    pickle.dump(a,file)

with open('text.txt','rb') as file2:
    b = pickle.load(file2)

print(type(b))



序列化方法

  • pickle.dump(obj, file, protocol=None,*,fix_imports=True) 该方法实现的是将序列化后的对象 obj 以二进制形式写入文件 file 中,进行保存。它的功能等同于 Pickler(file, protocol).dump(obj)

参数

含义

file

必须是以二进制的形式进行操作(写入)。

protocol

一共有5种不同的类型,即(0, 1, 2, 3, 4)。(0, 1, 2)对应的是 python 早期的版本,(3, 4)则是在 python3 之后的版本。此外,参数可选 pickle.HIGHEST_PROTOCOLpickle.DEFAULT_PROTOCOL

当前,python3.5 版本中:

- pickle.HIGHEST_PROTOCOL 的值为 4;

- pickle.DEFAULT_PROTOCOL 的值为 3;

- 当 protocol 参数为负数时,表示选择的参数是 pickle.HIGHEST_PROTOCOL

参考前文的案例如下:

import pickle
 
with open('svm_model_iris.pkl', 'wb') as f:
# file 为 svm_model_iris.pkl,并且以二进制的形式(wb)写入。
	pickle.dump(svm_classifier, f)



  • pickle.dumps(obj, protocol=None,*,fix_imports=True)pickle.dumps() 方法跟 pickle.dump() 方法的区别在于,pickle.dumps() 方法不需要写入文件中,它是直接返回一个序列化的 bytes 对象。


反序列化方法

  • pickle.load(file, *,fix_imports=True, encoding=”ASCII”. errors=”strict”) 该方法实现的是将序列化的对象从文件 file 中读取出来。它的功能等同于 Unpickler(file).load()
    读取的时候,参数 protocol 是自动选择的,load() 方法中没有这个参数。

参考如下:

import pickle
with open('svm_model_iris.pkl', 'rb') as f:
# file为 svm_model_iris.pkl,并且以二进制的形式(rb)读取。
    model = pickle.load(f)



  • pickle.loads(bytes_object, *,fix_imports=True, encoding=”ASCII”. errors=”strict”)pickle.loads() 方法跟 pickle.load() 方法的区别在于,pickle.loads() 方法是直接从bytes 对象中读取序列化的信息,而非从文件中读取。


  • pickle.Unpickler(file, *,fix_imports=True, encoding="ASCII". errors="strict"),
    pickle 模块提供了反序列化的面向对象的类方法,Pickler类有 load() 方法。
    Unpickler(file).load() 实现的功能跟 pickle.load() 是一样的。
    关于 Unpickler 类的其他 method,请参考官方 API

PDF

方法

df.to_html

对于 dataframe 可以先使用 df.to_html(),再使用工具将 markdown 转换为 pdf。参考 9



reportlab

参考这里 10


word

方法

python-docx

dataframe 写入 word,可参考 111213141516

官方文档说明参考这里 17


log, txt

参考这里 181920



读取

虽然,日志文件的后缀为 .log,但是基本上与 .txt 文本文件没有区别,按照一般读取文本文件的方式打开即可:

f =open("e:\\data.log") 
# 创建文件对象

f.read()
# 读取文件的完整内容

f.close()
# 关闭文件对象

又或者,

for line in open("e:\\data.log","r",encoding='UTF-8'):
	print(line)
# 按行读取 `data.log` 文件的内容

示例


f = open("e:\\data.log", 'r', encoding='UTF-8')
content = f.readlines()
prefix = content[:14]
f.close()

f = open("e:\\data.log", 'r', encoding='UTF-8')
content = f.readlines()
prefix = [i[:14] for i in content]
f.close()

f = open("e:\\data.log", 'r', encoding='UTF-8')
lines = f.readlines()
for line in lines:
	flag = re.search(keyword, line)
	if flag is not None:
		print(line)
		# 关键字所在的行
		print(flag.start(), flag.end())
		# 关键字在所在行的索引的起始与结束
f.close()