文件读写与异常处理
使用open()
函数打开文件,并且可以通过函数里的参数指定文件名、操作模式、字符编码等。
常用操作模式如下表:
操作模式 | 具体含义 |
---|---|
'r' | 读取 (默认) |
'w' | 写入(会先截断之前的内容) |
'x' | 写入,如果文件已经存在会产生异常 |
'a' | 追加,将内容写入到已有文件的末尾 |
'b' | 二进制模式 |
't' | 文本模式(默认) |
'+' | 更新(既可以读又可以写) |
如果想了解更多的操作模式,可点击此链接:菜鸟教程之file
在读取文件之后如果无法对自己程序的操作模式进行确定,可参考下图:
通过open函数打开一个文件之后,我们会得到一个返回文件对象,通过这个文件对象,我们可以实现对文件的读写操作。在使用完之后,我们一定要关闭文件,释放资源。关闭文件操作是close()
。
文件对象的操作函数
file.close()
关闭文件。关闭后文件不能再进行读写操作。
file.flush()
刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。
file.fileno()
返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。
file.read([size])
从文件读取指定的字节数,如果未给定或为负则读取所有。
file.readline([size])
读取整行,包括 “\n” 字符。
file.readlines([sizeint])
读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。
file.seek(offset[, whence])
移动文件读取指针到指定位置
file.tell()
返回文件当前位置。
file.truncate([size])
从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小。
file.write(str)
将字符串写入文件,返回的是写入的字符长度。
file.writelines(sequence)
向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。
open函数的参数
open函数的完整的语法格式
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明
file
: 必需,文件路径(相对或者绝对路径)。
mode
: 可选,文件打开模式
buffering
: 设置缓冲
encoding
: 一般使用utf8
errors
: 报错级别
newline
: 区分换行符
closefd
: 传入的file参数类型
opener
: 设置自定义开启器,开启器的返回值必须是 一个打开的文件描述符。
这里介绍一个小绝招:当我们使用open函数时,每次在不用文件时都需要使用close()函数关闭文件,会很麻烦。所以我们一般都不会使用这种方式,推荐大家使用:with open() as 别名:这种方式,这种方式会在我们使用完文件之后,自动帮助我们关闭文件,继而我们后续就不需要手动输入代码关闭文件。
读写文本文件
读文件
使用open函数打开一个文件,一般来说都会指定操作模式,如果不指定,默认是读模式,'r’
# 返回的是全部的歌词
with open('周杰伦-青花瓷.txt','r',encoding='utf-8') as file:
print(file.read())
也可以使用for-in循环逐行读取,也可以使用readlines将文件按行读取到容器中。
with open('周杰伦-青花瓷.txt','r',encoding='utf-8')as file:
# print(file.read())
for line in file:
print(line,end='')
lines = file.readlines() # lines是一个列表
for line in lines:
print(line,end='')
readlines:读取多行(全部)
readline:读一行
with open('周杰伦-青花瓷.txt','r',encoding='utf-8')as file:
print(file.readline())
写文件
如果需要向文件中写入内容,可以指定操作模式为’w’或者a,'w’模式写入内容会覆盖之前的内容,'a’是在内容的尾部追加新内容。
with open('周杰伦-青花瓷.txt','a',encoding='utf-8')as file:
file.write('\n歌曲:青花瓷')
file.write('\n演唱:周杰伦')
异常处理
在编写程序时,很多时候报错是很普遍的,但是很多时候我们不想要程序报错,哪怕真的报错了,也希望下面的代码也可以继续执行,而不是停留在报错行,通常使用异常机制对这些问题进行处理。
对于异常处理,与之相关的关键字有try
,except
,else
,finally
,raise
。
对于异常处理,有以下几种方式:
try..except
try...except...else
try...except...else...finally
raise触发异常
x = 6
if x > 1:
raise Exception('x 不能大于 1。x : {}'.format(x))
# 返回
Exception: x 不能大于 1。x : 6
读写二进制文件
读写二进制文件的操作与上面的读写文件基本相同,只是将open函数的操作模式改变一下。
读二进制文件:操作模式----->'rb'
写二进制文件:操作模式----->'wb'
只要涉及二进制文件:往往都是在操作模式后面加上‘b’。
python读取csv文件
CSV文件介绍
CSV(Comma Separated Values)全称逗号分隔值文件是一种简单、通用的文件格式,被广泛的应用于应用程序(数据库、电子表格等)数据的导入和导出以及异构系统之间的数据交换。因为CSV是纯文本文件,不管是什么操作系统和编程语言都是可以处理纯文本的,而且很多编程语言中都提供了对读写CSV文件的支持,因此CSV格式在数据处理和数据科学中被广泛应用。
CSV文件有以下特点:
- 纯文本,使用某种字符集(如ASCII、Unicode、GB2312)等);
- 由一条条的记录组成(典型的是每行一条记录);
- 每条记录被分隔符(如逗号、分号、制表符等)分隔为字段(列);
- 每条记录都有同样的字段序列。
将数据写入csv文件
在进行csv文件操作是需要调用Python中的csv模块,该模块的writer
函数会返回一个csvwriter
对象,通过该对象的writerow
或writerows
方法就可以将数据写入到CSV文件中。
import csv
import random
# 如果文件存在则直接在里面添加,否则创建文件之后再进行添加
with open('scores.csv','w',encoding='utf-8',newline='')as file:
writer = csv.writer(file)
# 写入表头
writer.writerow(['name','chinese','math','english'])
names = ['刘备','关羽','张飞']
for i in range(3):
# 使用随机生成成绩
chinese_score = random.randint(40,100)
math_score = random.randint(40,100)
english_score = random.randint(40,100)
# 写入名字和成绩
writer.writerow([names[i],chinese_score,math_score,english_score])
上面的
writer
函数,该函数除了传入要写入数据的文件对象外,还可以dialect
参数,它表示CSV文件的方言,默认值是excel
。除此之外,还可以通过delimiter
、quotechar
、quoting
参数来指定分隔符(默认是逗号)、包围值的字符(默认是双引号)以及包围的方式。其中,包围值的字符主要用于当字段中有特殊符号时,通过添加包围值的字符可以避免二义性
示例:
import csv
with open('scores.csv', 'r') as file:
reader = csv.reader(file, delimiter='|')
for line in reader:
print(reader.line_num, end='\t')
for elem in line:
print(elem, end='\t')
print()
Excel操作
Python操作Excel需要三方库的支持,如果要兼容Excel 2007以前的版本,也就是xls
格式的Excel文件,可以使用三方库xlrd
和xlwt
,前者用于读Excel文件,后者用于写Excel文件。如果使用较新版本的Excel,即操作xlsx
格式的Excel文件,也可以使用openpyxl
库,当然这个库不仅仅可以操作Excel,还可以操作其他基于Office Open XML的电子表格文件。
使用xlrd读Excel文件
xlrd读取的是xls文件,如果需要使用它读xlsx文件,新版本的xlrd不支持,我们需要下载的版本是1.2.0版本的。
具体xlrd的读文件操作以代码形式展示:
import xlrd
# 工作簿--->一个Excel文件---->workbook
wb = xlrd.open_workbook('阿里巴巴2020年股票数据1.xls')
# 获取所有工作表
print(wb.sheet_names())
# 获取指定工作表,worksheet
sheet = wb.sheet_by_name('股票数据')
sheet1 = wb.sheet_by_index(0)
print(type(sheet),type(sheet1))
# # 获取行数列数
print(sheet.nrows,sheet.ncols)
# # 获取单元格的数据
print(sheet.row(0)) # 一行
print(sheet.row(0)[0]) #第一行中某一个具体的数据
print('---------------------')
# 指定某行从第几列输出到第几列
print(sheet.row_slice(1,start_colx=0,end_colx=3))
print(sheet.col(1))
print(sheet.col_slice(4, start_rowx=1, end_rowx=11))
# 获取单元格数据--->cell--->value
cell = sheet.cell(2, 2)
print(cell.value)
# 遍历表单,根据行列索引,不包括表头
print(f'交易日期\t\t\t最高价\t\t最低价\t\t开盘价\t\t收盘价\t\t成交量\t\t调整收盘价')
for row in range(1, sheet.nrows):
for col in range(sheet.ncols):
value = sheet.cell(row, col).value
if col == 0:
# 处理时间日期
# year, month, date, *_ = xlrd.xldate_as_tuple(value, 0)
curr_date = xlrd.xldate_as_datetime(value,0)
print(curr_date.strftime('%Y年%m月%d日'),end='\t')
# print(f'{year}年{month:0>2d}月{date:0>2d}日', end='\t')
elif col == 5:
print(f'{int(value):<10d}', end='\t')
else:
print(f'{value:.4f}', end='\t')
print()
xlwt写Excel文件
import random
import xlwt
student_names = ['关羽', '张飞', '赵云', '马超', '黄忠']
scores = [[random.randint(40, 100) for _ in range(3)] for _ in range(5)]
# 创建工作簿对象(Workbook)
wb = xlwt.Workbook()
# 创建工作表对象(Worksheet)
sheet = wb.add_sheet('一年级二班')
# 添加表头数据
titles = ('姓名', '语文', '数学', '英语')
for index, title in enumerate(titles):
sheet.write(0, index, title)
# 将学生姓名和考试成绩写入单元格
for row in range(len(scores)):
sheet.write(row + 1, 0, student_names[row])
for col in range(len(scores[row])):
sheet.write(row + 1, col + 1, scores[row][col])
# 保存Excel工作簿
wb.save('考试成绩表.xls')
调整单元格样式
背景色调整
第一行的表头单元格修改为黄色
header_style = xlwt.XFStyle()
pattern = xlwt.Pattern()
pattern.pattern = xlwt.Pattern.SOLID_PATTERN
# 0 - 黑色、1 - 白色、2 - 红色、3 - 绿色、4 - 蓝色、5 - 黄色、6 - 粉色、7 - 青色
pattern.pattern_fore_colour = 5
header_style.pattern = pattern
titles = ('姓名', '语文', '数学', '英语')
for index, title in enumerate(titles):
sheet.write(0, index, title, header_style)
修改字体
font = xlwt.Font()
# 字体名称
font.name = '华文楷体'
# 字体大小(20是基准单位,18表示18px)
font.height = 20 * 18
# 是否使用粗体
font.bold = True
# 是否使用斜体
font.italic = False
# 字体颜色
font.colour_index = 1
header_style.font = font
表头垂直居中对齐
align = xlwt.Alignment()
# 垂直方向的对齐方式
align.vert = xlwt.Alignment.VERT_CENTER
# 水平方向的对齐方式
align.horz = xlwt.Alignment.HORZ_CENTER
header_style.alignment = align
调整行高列宽
# 设置行高为40px
sheet.row(0).set_style(xlwt.easyxf(f'font:height {20 * 40}'))
titles = ('姓名', '语文', '数学', '英语')
for index, title in enumerate(titles):
# 设置列宽为200px
sheet.col(index).width = 20 * 200
# 设置单元格的数据和样式
sheet.write(0, index, title, header_style)
xlrd,xlwt这两个模块将Excel的读写操作是分开的,在进行文件操作时有点麻烦,所以推荐大家使用另一个Excel文件操作模块 openpyxl,它的功能和xlrd,xlwt相差不大,甚至强于他们,它将文件读写操作合并在一起,调用这个模块就可以对文件进行读写,同时都支持调整字体,颜色,对齐方式等,基本上excel的功能都有。
详细操作大家可以去官方API查看:
xlrd官方文档
xlwt官方文档
转载 openpyxl常用API
操作PDF文件
对PDF操作需要借助三方库PyPDF2
对PDF进行文字提取其实效率并不高,这里不做讲解。创建PDF亦是如此,这里只是讲一下如何给PDF添加水印以及对PDF加密。
添加水印、进行加密
在进行添加水印,我们需要准备另一个水印的PDF文件,其实添加水印实际上就是将两个PDF文件合在一起。
import PyPDF2
import os
from PyPDF2.pdf import PageObject
path = 'pdffile' # 当前PDF所在的路径,这里是相对于我的工作路径
filenames = os.listdir(path)
# 读取水印PDF文件
reader1 = PyPDF2.PdfFileReader('watermark.pdf')
# 水印在第一页,就只拿第一页
watermark_page = reader1.getPage(0)
# 创建一个PDF对象
writer = PyPDF2.PdfFileWriter()
# 将文件夹里面的所有PDF文件读取
for filename in filenames:
reader2 = PyPDF2.PdfFileReader(path+'/'+filename)
for page in range(reader2.numPages):
curr_page = reader2.getPage(page) # type: PageObject
# 将需要添加水印的PDF文件与水印文件合并
curr_page.mergePage(watermark_page)
# 创建PDF,将加了水印的PDF写在另一个创建的PDF里面
writer.addPage(curr_page)
# 给PDF加密,括号里面的是密码,相反decrypt()是解密,括号里面是密码
writer.encrypt('123abc')
# 保存文件
with open(f'pdffile/{filename[:-4]}_watermark.pdf','wb')as file:
writer.write(file)
我这里是对多个文件进行操作,对一个一是这种操作
正则表达式
正则表达式理解起来不容易,这里不做陈述。
转载:30分钟了解正则表达式
符号 | 解释 | 示例 | 说明 |
---|---|---|---|
. | 匹配任意字符 | b.t | 可以匹配bat / but / b#t / b1t等 |
\w | 匹配字母/数字/下划线 | b\wt | 可以匹配bat / b1t / b_t等 但不能匹配b#t |
\s | 匹配空白字符(包括\r、\n、\t等) | love\syou | 可以匹配love you |
\d | 匹配数字 | \d\d | 可以匹配01 / 23 / 99等 |
\b | 匹配单词的边界 | \bThe\b | |
^ | 匹配字符串的开始 | ^The | 可以匹配The开头的字符串 |
$ | 匹配字符串的结束 | .exe$ | 可以匹配.exe结尾的字符串 |
\W | 匹配非字母/数字/下划线 | b\Wt | 可以匹配b#t / b@t等 但不能匹配but / b1t / b_t等 |
\S | 匹配非空白字符 | love\Syou | 可以匹配love#you等 但不能匹配love you |
\D | 匹配非数字 | \d\D | 可以匹配9a / 3# / 0F等 |
\B | 匹配非单词边界 | \Bio\B | |
[] | 匹配来自字符集的任意单一字符 | [aeiou] | 可以匹配任一元音字母字符 |
[^] | 匹配不在字符集中的任意单一字符 | [^aeiou] | 可以匹配任一非元音字母字符 |
* | 匹配0次或多次 | \w* | |
+ | 匹配1次或多次 | \w+ | |
? | 匹配0次或1次 | \w? | |
{N} | 匹配N次 | \w{3} | |
{M,} | 匹配至少M次 | \w{3,} | |
{M,N} | 匹配至少M次至多N次 | \w{3,6} | |
| | 分支 | foo|bar | 可以匹配foo或者bar |
(?#) | 注释 | ||
(exp) | 匹配exp并捕获到自动命名的组中 | ||
(?<name>exp) | 匹配exp并捕获到名为name的组中 | ||
(?:exp) | 匹配exp但是不捕获匹配的文本 | ||
(?=exp) | 匹配exp前面的位置 | \b\w+(?=ing) | 可以匹配I’m dancing中的danc |
(?<=exp) | 匹配exp后面的位置 | (?<=\bdanc)\w+\b | 可以匹配I love dancing and reading中的第一个ing |
(?!exp) | 匹配后面不是exp的位置 | ||
(?<!exp) | 匹配前面不是exp的位置 | ||
*? | 重复任意次,但尽可能少重复 | a.*b a.*?b | 将正则表达式应用于aabab,前者会匹配整个字符串aabab,后者会匹配aab和ab两个字符串 |
+? | 重复1次或多次,但尽可能少重复 | ||
?? | 重复0次或1次,但尽可能少重复 | ||
{M,N}? | 重复M到N次,但尽可能少重复 | ||
{M,}? | 重复M次以上,但尽可能少重复 |
正则表达式使用re模块
常用函数及说明
函数 | 说明 |
---|---|
compile(pattern, flags=0) | 编译正则表达式返回正则表达式对象 |
match(pattern, string, flags=0) | 用正则表达式匹配字符串 成功返回匹配对象 否则返回None |
search(pattern, string, flags=0) | 搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None |
split(pattern, string, maxsplit=0, flags=0) | 用正则表达式指定的模式分隔符拆分字符串 返回列表 |
sub(pattern, repl, string, count=0, flags=0) | 用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count 指定替换的次数 |
fullmatch(pattern, string, flags=0) | match 函数的完全匹配(从字符串开头到结尾)版本 |
findall(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回字符串的列表 |
finditer(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回一个迭代器 |
purge() | 清除隐式编译的正则表达式的缓存 |
re.I / re.IGNORECASE | 忽略大小写匹配标记 |
re.M / re.MULTILINE | 多行匹配标记 |