文件操作
文件操作是每一门编程语言中都必不可少的一项语法,通过文件,可以实现数据持久化存储,测试数据驱动文件的处理,程序配置文件的处理等。
在程序中操作文件和使用图形界面操作文件的过程基本一致,都要进行找到文件位置,打开文件,读写文件,关闭文件等操作。
打开文件
Python 使用 open
方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。
完整格式:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
简化格式:
open(file, mode='r', encoding=None)
- file: 必需,指定打开文件的路径(相对或者绝对路径)。
- mode: 可选,文件打开模式,默认为
r
只读模式 - encoding: 一般使用
utf8
mode参数常见下表:
字符 | 含意 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
w | 以只写方式打开文件。如果该文件已存在则覆盖文件。如果该文件不存在则创建新文件。 |
a | 以追加写入方式打开文件,如果文件存在则在末尾追加,文件不存在则创建新文件 |
b | 二进制模式 |
t | 文本模式(默认) |
# 以写入文件打开 index.html 文件
file = open("index.html", "w")
文件关闭
文件在操作完以后,需要将其关闭,close()
方法用于关闭一个已打开的文件。
关闭后的文件不能再进行读写操作, 否则会触发 ValueError
错误。
close()
方法允许调用多次。
使用 close()
方法关闭文件是一个好的习惯。
格式:fileObject.close()
# 以写入文件打开 index.html 文件
file = open("index.html", "w")
# 关闭文件
file.close()
文件写入
write() 方法
write()
方法用于向文件中写入指定字符串。如果文件打开模式为b
,则要将字符串转换成 bytes
类型的二进制字符串,函数返回成功写入数据的长度。
格式:fileObject.write( [ str ])
# 以写入文件打开 index.html 文件
file = open("index.html", "w")
# 写入数据
file.write("<h1>文件写入标题</h1>")
file.write("\n")
file.write("<p>文件写入内容。。。。。。</p>")
# 关闭文件
file.close()
writelines() 方法
writelines()
方法用于向文件中写入一序列的字符串。
这一序列字符串可以是由迭代对象产生的,如一个字符串列表。
注意:不要被方法名所迷惑,如果每个元素独占一行,需要在数据后指定换行符 \n
。
格式:fileObject.writelines(seq)
datas = ["AAAAAAAAAAAA\n","BBBBBBBBBBBB\n","CCCCCCCCCCCC\n","DDDDDDDDDDDD\n"]
file = open('data.txt',"w")
file.writelines(datas)
file.close()
读取文件
read() 方法
read()
方法用于从文件读取指定的字节数,如果未给定或为负则读取所有。
格式:fileObject.read([size=-1])
file = open('data.txt',"r")
# 读取10个字符
content = file.read(10)
print(content)
# 读取所有内容
content = file.read()
print(content)
file.close()
readline() 方法
readline()
方法用于从文件读取整行,包括 \n
字符。如果指定了一个非负数的参数,则返回指定大小的字节数,包括 \n
字符。
格式:fileObject.readline(size=-1)
file = open('data.txt',"r")
# 读取10个字符
content = file.readline(10)
print(content)
# 读取文件指针所在行剩余所有内容
content = file.readline()
print(content)
file.close()
readlines()方法
readlines()
方法用于读取所有行(直到结束符 EOF)并返回列表。
格式:fileObject.readlines()
file = open('data.txt',"r")
# 以行为单位读取文件所有的内容
contents = file.readlines()
print(contents)
file.close()
调试与分析
在编写程序过程中,出现错误是再所难免的,出现错误后,如何能通过报错信息,快速找出并修复错误,是代码开发过程中非常重要的技能。
错误分析
程序出现错误并中断结束后,出现报错信息的错误都是不可怕的,大多都是一些语法性的错误,通过错误提示信息,就可以快速定位和解决错误。
错误分析:
- 错误所在的文件
- 错误所在的行
- 错误出现的代码
- 错误类型
- 错误原因描述
有时候通过报错信息,并不能直接定位出错误,要通过报错信息,及程序的上下文逻辑来分析真正的报错原因。
在上面的错误中,共提示了两处报错位置,分别是12行和7行,这是代码追踪提示。
但真正的错误并不在这里,通过错误原因描述发现,是在执行range()函数时,并不能将字符串类型的参数解释成一个数字。
从代码实现逻辑上看,output
函数并没有任何问题,结合上下文的代码逻辑发现,问题出在 getInputData
函数中的数据获取,从键盘输入的所有内容都是以字符串形式保存到程序变量中,程序要求获得一个数字,那么在键盘输入后,应该使用强制类型转换,将输入数据转换成数字。
n = input("请输入一个数字:")
修改为n = int(input("请输入一个数字:"))
print信息调试
很多人由于英文不太好,在查看报错信息时很吃力,也可以通过 print()
函数,自行输出信息来定位错误位置,虽然这种方式可以解决问题,但还是要慢慢学习,掌握如何查看报错提示。
示例代码:
def getInputData():
print("input run")
n = input("请输入一个数字:")
msg = input("请输入一个数据:")
return n,msg
def outputData(n,msg):
print("output run")
for i in range(n):
print("output forin run")
print(msg)
if __name__ == '__main__':
n,msg = getInputData()
outputData(n, msg)
运行结果:
input run
请输入一个数字:1
请输入一个数据:1
output run
Traceback (most recent call last):
File "/Users/liusuhui/Desktop/RecordCode/main.py", line 15, in <module>
outputData(n, msg)
File "/Users/liusuhui/Desktop/RecordCode/main.py", line 9, in outputData
for i in range(n):
TypeError: 'str' object cannot be interpreted as an integer
Process finished with exit code 1
在示例代码中,加入了三条 print()
语句,用来输出一些信息,通过运行结果可以看出,input run
和 output run
都被正常输出,而 output forin run
没有输出,说明程序在输出该语句之前出现错误,此时就可以通过检查语法信息,上下文逻辑等来判断具体错误原因。
print()
语句在调试代码时,两条语句之间包含多少代码,视具体情况而定。不是必须在每条语句前后都加 print()
输出,在错误调试完成后,需要把输出注释或删除掉。
什么是异常
错误 与 异常的区别?
- 错误与异常都是在程序编译和运⾏时出现的错误
- 异常可以被开发⼈员捕捉和处理
- 错误⼀般是系统错误,⼀般不需要开发⼈员处理(也⽆法处理),⽐如内存溢出
什么是异常?
- 异常即是⼀个事件,该事件会在程序执⾏过程中发⽣,影响了程序的正常执⾏。
- 有些是由于拼写、配置、选项等等各种引起的程序错误,有些是由于程序功能处理逻辑不完善引起的漏洞,这些统称为程序中的异常
常见的异常类型
- 除零异常、名称异常、索引异常、键异常、值异常、属性异常等等
##语法错误与定位
异常处理流程:
- 检测到错误->引发异常->捕获异常操作
异常解决⽅案
- 如果是拼写、配置等引起的错误,根据出错信息进⾏排查错误出现的位置进⾏解决
- 如果是程序设计不完善引起的漏洞,根据漏洞的情况进⾏设计处理漏洞的逻辑
##异常捕获、异常处理
# 相除
# def div(a, b):
# if b != 0:
# return a / b
# else:
# print('分母不能为0')
# return 0
def div(a, b):
return a / b
f = open('data.txt')
try:
print(div(1, 1))
list1 = [1, 2, 3]
print(list1[3])
f.readlines()
except Exception as e:
print(e)
print('这里有个异常')
finally: # finally最终都会被执行,无论有异常还是没有异常的情况
print('finally')
f.close()
def set_age(num):
if num <= 0 or num > 200:
raise ValueError(f'值错误:{num}')
else:
print(f'设置的年龄为:{num}')
set_age(-1)
⾃定义异常
语法
raise [Exception [, args [, traceback]]]
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class MyException(Exception):
def __init__(self, msg):
print(f'这是一个异常:{msg}')
def set_age(num):
if num <= 0 or num > 200:
raise MyException(f'值错误:{num}')
else:
print(f'设置的年龄为:{num}')
set_age(-10)
debug调试与分析
##调试的概念与技术体系
- 程序调试是将编制的程序投⼊实际运⾏前,⽤⼿⼯或编译程序等⽅法进⾏测
试,修正【语法错误和逻辑错误】的过程。 - 语法错误:编写的python语法不正确,程序编译失败。
- 逻辑错误:代码本⾝能够正常执⾏,但是执⾏完成的结果不符合预期结果。
- 什么是bug:bug是计算机领域专业术语(⼩昆⾍; ⾍⼦),计算机⾥叫漏洞,隐藏在程序中的⼀些未被发现的缺陷或问题统称为bug(漏洞)
程序调试
- 1、语法错误
- 类型错误,语法错误,缩进错误,索引错误,键错误
- 2、逻辑错误
- 业务逻辑错误,并不会报错
调试方法
- 1、对应位置使⽤
print
或者logging
打印⽇志信息 - 2、启动断点模式debug调试
debug调试
还可以通过 PyCharm 的 debug
功能来调试程序,通过 debug
功能,还可以监控程序的执行过程。
在使用debug功能时,需要配合程序断点来进行调试。
程序断点
使用 PyCharm 编写代码时,可以在行号后通过点击添加删除断点。
断点的作用是在debug调试程序时,遇到断点程序就会暂停执行,通过点击控制按钮,控制程序向下执行。
调试控制
程序打好断点后,点击debug即可进入debug模式,程序遇到断点就会暂停执行,此时就需要通过控制按钮来控制程序的执行
横向按钮
-
Step Over
: 步过按钮,将函数做为一条语句执行,不进入函数内部执行。 -
Step Into
: 单步执行,会进入到函数内部逐条执行代码。 -
Step Into My Code
: 单步执行,只进入自定义函数内部,不会进入系统函数内部。 -
Step Out
: 步出按钮,跳出当前函数体,返回到此函数调用位置 -
Run to Cursor
: 运行到光标处,当调试程序时,如果某一行没有打断点,又想暂停,可以将光标移动到目标行,点击该按钮 -
Evaluate Expression
: 评估表达式,高级用法,可以在调试过程中查看程序的中间过程,比如查看参数 n 的类型。
竖向按钮
-
Rerun main
: 重新运行 debug 功能 -
Modify Run Configuration
: 修改运行配置 -
Resume Program
: 继续执行,运行到下一断点处,如果没有,程序运行结束 -
Stop main
: 停止 Debug -
View Breakpoints
: 显示程序中所有的断点。 -
Mute Breakpoints
: 让所有断点失效,使用后所有断点为灰色,debug时,代码不会在断点处暂停。 -
Pin Tab
: 钉住当前调试窗口标签,防止关闭。
异常处理
编写程序时,即使语句或表达式使用了正确的语法,执行时仍可能触发错误。执行时检测到的错误称为异常,大多数异常不会被程序处理,程序会中断运行,并抛出异常信息。
如果不想发生异常时,程序被中断执行,可以编写程序处理选定的异常。
try-except
Python 使用 try/except
语句捕捉异常。
try/except
语句用来检测 try
语句块中的错误,从而让 except
语句捕获异常信息并处理。
如果你不想在异常发生时结束你的程序,只需在try里捕获它。
n1 = int(input("请输入第一个数:"))
n2 = int(input("请输入第二个数:"))
result = 0
try:
result = n1 / n2
except Exception:
print("除数不能为0")
print(result)
file = open("data.txt","r")
try:
# 写入数据时可能会有问题
file.write("写入的数据")
except IOError as err:
print("文件不能写入", err)
file.close()
捕捉多个异常
如果一段代码可能会发生多种异常,并想在程序中都想处理,可以使用多个 except
分别捕捉异常。
可以捕捉 Exception
异常类型来处理所有的异常,如果有多个时,必须放在最后捕捉该异常,否则无法处理到其它异常。
file = open("data.txt","r")
try:
# 写入数据时可能会有问题
# file.write("写入的数据")
# print(a)
# print(3 / 0)
# print([][10])
print("hello" + 100)
except IOError as err:
print("文件不能写入", err)
except NameError:
print("标识符没有定义")
except ZeroDivisionError:
print("除数不能为0")
except IndexError:
print("下标越界了")
except Exception:
print("程序运行出错,请检查代码")
file.close()
else 操作
Python 使用 else
在处理在代码无异常时的后续操作。
try:
n = input("请输入一个数字:")
num = int(n)
except Exception:
print("元素无法转换为数字")
else:
print("转换后成功",num)
finally 操作
Python 使用 finally
处理无论异常是否发异,都要执行的代码,一般用来完成清理工作。
try:
file = open("data.txt","r")
# file.write("A")
except Exception:
print("文件操作报错")
finally:
print("文件已关闭")
file.close()