Python ❀ 文件与异常

Posted 无糖可乐没有灵魂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python ❀ 文件与异常相关的知识,希望对你有一定的参考价值。

文章目录

1、文件中读取数据


文本文件可以存储的数据较多,因此Python需要使用文本文件中的信息;

1.1 读取文件

创建一个文件,包含一些数据,使用Python读取文件内容;

with open('test.txt') as fp:
    contents = fp.read()
    print(contents)

输出结果:

this is test1!
this is test2!
this is test3!
this is test4!

1.2 文件路径

大多数情况下,Python需要打开的文件路径并不是当前Python文件创建的文件路径下,因此就需要告诉Python去那个地方寻找目标文件;Linux系统使用斜杠 / 区分目录层级,而Windows系统使用反斜杠 \\ 区分目录层级,反斜杠在Python中以为转义字符,因此在Windows系统中就需要对目录层级进行转义方可正确识别;若目标文件在当前Python文件目录或当前目录下,推荐使用相对路径,若在其他位置,推荐使用绝对路径寻找目标文件;

  • 在Windows系统下使用绝对路径找寻文件;
file_path = "D:\\\\Python\\\\Test\\\\Source\\\\StudyCode\\\\test.txt"

with open(file_path) as fp:
    contents = fp.read()
    print(contents)
  • 在Linux系统下使用绝对路径找寻文件;
[root@VM-8-10-centos ~]# python3 a.py 
this is linux1

[root@VM-8-10-centos ~]# cat a.txt
this is linux1
[root@VM-8-10-centos ~]# cat a.py
file_path = '/root/a.txt'

with open(file_path) as fp:
    contents = fp.read()
    print(contents)
[root@VM-8-10-centos ~]# python3 a.py 
this is linux1

read()到达文件末尾返回一个空白字符串,将这个空白字符串显示为一个空行,可以使用rstrip()删除末尾的空白

[root@VM-8-10-centos ~]# cat a.py 
file_path = '/root/a.txt'

with open(file_path) as fp:
    contents = fp.read()
    print(contents.rstrip())
[root@VM-8-10-centos ~]# python3 a.py 
this is linux1

1.3 逐行读取

读取文件时,需要检查文件内的每一行;若需要从文件内查找某个特定行,就需要逐行读取文件内容,并返回到指定位置;

with open("test.txt") as fp:
    for line in fp:
        print(line)

输出结果:

this is test1!

this is test2!

this is test3!

this is test4!

将文件读取的内容存储在变量中,此时打印每一行都会出现空行,由于每行数据都存在一个换行符,print函数也会加上此换行符,因此每行末尾都会有两个换行符,一个是print语句自身的换行,一个是文件内每行的换行,需要消除这些空行,就需要使用rstrip();

with open("test.txt") as fp:
    for line in fp:
        print(line.rstrip())

输出结果:

this is test1!
this is test2!
this is test3!
this is test4!

1.4 创建一个包含文件各行内容的列表

使用with时,open()返回的文件对象只能在with代码内可用,如果需要其他处使用,则需要将文件内容存储至一个列表中,并在with代码外使用此列表,就可以处理文件的各个部分;

with open("test.txt") as fp:
    lines = fp.readlines()
    print(lines)

输出结果:

['this is test1!\\n', 'this is test2!\\n', 'this is test3!\\n', 'this is test4!']

1.5 使用文件内容

将文件读取至内存时,就可以修改这些数据;

with open("test.txt") as fp:
    lines = fp.readlines()

st1 = ''
for line in lines:
    # 修改注意消除空行与空白字符
    st1 += line.strip()

print(st1)
print(len(st1))

输出结果:

this is test!this is test!this is test!this is test!
52

2、写入文件


保存数据最简单的方法就是将其写入到文件中,通过输出写入文件,即便关闭了程序窗口,这些数据仍然存在,不会被修改或删除;

2.1 写入空白文件

若需要将文本写入文件,需要使用open()函数的一个实参w,告知Python需要写入打开的文件;open()函数中第一个实参为打开的文件路径,可以为变量值;第二个实参为文件模式,支持 读取模式(r)写入模式(w)附加模式(a)读取和写入模式(r+),默认选择模式为读取模式,在写入模式或附加模式下,若目标文件不存在,在Python会自动创建一个空白文件用于存储数据;

fp = 'test.txt'

with open(fp,'w') as file:
    file.write('this is test!')

输出结果:

# 查看目标文件内容
this is test!

2.2 写入多行

函数write()不会再写入的文件末尾添加换行符,因此若是需要写入多行数据,需要在代码中添加换行符,以进行换行写入操作;

  • 不添加换行符
fp = 'test.txt'

with open(fp,'w') as file:
    file.write('this is test1!')
    file.write('this is test2!')

输出结果:

this is test1!this is test2!
  • 添加换行符
fp = 'test.txt'

with open(fp,'w') as file:
    file.write('this is test1!\\n')
    file.write('this is test2!')

输出结果:

this is test1!
this is test2!

除了换行符,还支持其他操作符,如制表符、空格等常见操作符;

2.3 附加到文件

若需要给文件添加内容,而不是覆盖原有内容,则需要使用附加模式(a)打开文件;以附加模式打开文件,Python不会清空之前的数据,而是将新数据添加至文件末尾;

fp = 'test.txt'

with open(fp,'a') as file:
    file.write('this is test3!\\n')
    file.write('this is test4!')

输出结果:

this is test1!
this is test2!
this is test3!
this is test4!

3、异常处理


Python使用被称为异常的特殊对象来管理程序并执行期间发生的错误,每当发生让Python不知错误时,就会产生一个异常对象;若是编写了异常处理代码,则会继续运行;若未编写异常处理代码,则会返回一个traceback,包含了异常的报告;

3.1 处理ZeroDivisionError异常

下面引入一个异常,以0做除数;

print(1/0)

输出结果:

Traceback (most recent call last):
  File "D:\\Python\\Test\\Source\\StudyCode\\05_study_test.py", line 1, in <module>
    print(1/0)
ZeroDivisionError: division by zero

首先ZeroDivisionError指出了异常对象是什么类型,其次division by zero说明了异常出现的原因;

3.2 使用try-except处理异常

当你认为可能会发生错误时,可以编写一个处理异常代码来处理可能引发的异常;

try:
    print(1/0)
except ZeroDivisionError:
    print("divide is not zero!")

输出结果:

divide is not zero!

try接收可能会出现异常的代码内容,except需要指定错误类型,如果错误类型匹配,则执行下面的代码内容;

try:
    [可能出现异常的代码]
except [异常类型]:
    [异常类型匹配成后执行的代码]

3.3 使用异常避免崩溃

当程序未执行完成出现异常时,会直接中断当前代码执行过程,返回异常对象;如果能够正确处理异常,就可以避免代码出现崩溃现象;

print('Give me to numbers\\nand i will divide them ')
fir_number = input('First number is :')
last_number = input('Last number is :')
answer = int(fir_number) / int(last_number)
print(answer)

输出结果:

Give me to numbers
and i will divide them 
First number is :5
Last number is :0
Traceback (most recent call last):
  File "D:\\Python\\Test\\Source\\StudyCode\\05_study_test.py", line 6, in <module>
    answer = int(fir_number) / int(last_number)
ZeroDivisionError: division by zero

程序崩溃时,无法继续执行后续代码,会导致用户使用效果极差;因此在可能出现异常的地方,需要使用异常处理代码来避免异常导致的代码崩溃出现;

print('Give me to numbers\\nand i will divide them ')
fir_number = input('First number is :')
last_number = input('Last number is :')
try:
    answer = int(fir_number) / int(last_number)
    print(answer)
except ZeroDivisionError:
    print('division not by zero')

输出结果:

Give me to numbers
and i will divide them 
First number is :5
Last number is :0
division not by zero

3.4 else代码块

在try-except代码中还有一个else代码块,else执行为try后结果;

print('Give me to numbers\\nand i will divide them ')
fir_number = input('First number is :')
last_number = input('Last number is :')
try:
    answer = int(fir_number) / int(last_number)
except ZeroDivisionError:
    # 当try代码执行过程匹配到ZeroDivisionError异常时,运行except代码内容
    print('division not by zero')
else:
    # 当try代码执行正常无异常时,运行else代码内容
    print(answer)

输出结果:

Give me to numbers
and i will divide them 
First number is :5
Last number is :1
5.0

3.5 处理FileNotFoundError异常

使用文件时,最常见的问题就是文件路径错误导致文件打开失败,

# 文件路径选择一个不存在的文件
filename = 'file.txt'
with open(filename,'r') as fp:
    content = fp.read()
print(content)

输出结果:

Traceback (most recent call last):
  File "D:\\Python\\Test\\Source\\StudyCode\\05_study_test.py", line 3, in <module>
    with open(filename,'r') as fp:
FileNotFoundError: [Errno 2] No such file or directory: 'file.txt'

由于文件不存在,因此报出FileNotFoundError异常,此异常的触发是由于open()函数未找到对应的file.txt文件,因此将此处代码使用try-except进行异常处理就可以避免代码崩溃;

filename = 'file.txt'
try:
    with open(filename) as fp:
        content = fp.read()
except FileNotFoundError:
    print( filename + ' is not found! ')
else:
    print(content)

输出结果:

file.txt is not found! 

3.6 分析文本

当经过异常处理后的代码可以使用else代码块继续执行异常判断结果,因此就可以对其结果进行其他操作;
split()以空格为分隔符号将字符串拆分成多个部分,并将其存储至一个列表中;

filename = 'test.txt'
try:
    with open(filename) as fp:
        content = fp.read()
except FileNotFoundError:
    print( filename + ' is not found! ')
else:
    num_words = len(content.split())
    print('the file ' + filename + ' has about ' + str(num_words) + ' words ')

输出结果:

the file test.txt has about 12 words 

3.7 使用多个文件

下面将统计单词的代码变更为函数,并使用遍历方法,输入多个文件,执行函数内异常判断与统计单词;

# 函数
def count_words(filename):
    try:
        with open(filename) as fp:
            content = fp.read()
    except FileNotFoundError:
        print(filename + ' is not found! ')
    else:
        num_words = len(content.split())
        print('the file ' + filename + ' has about ' + str(num_words) + ' words ')\\

if __name__ == '__main__':
    filenames = ['test.txt','a.txt','b.txt']
    # 遍历多个文件名称
    for filename in filenames:
        count_words(filename)

输出结果:

the file test.txt has about 12 words 
a.txt is not found! 
b.txt is not found! 

3.8 异常触发无回显

一般情况下,当代码出现异常时不能出现返回信息,继续让代码执行,直到执行结束;

def count_words(filename):
    try:
        with open(filename) as fp:
            content = fp.read()
    except FileNotFoundError:
        # 匹配异常时,什么都不执行
        pass
    else:
        num_words = len(content.split())
        print('the file ' + filename + ' has about ' + str(num_words) + ' words ')\\

if __name__ == '__main__':
    filenames = ['a.txt','b.txt','test.txt']
    for filename in filenames:
        count_words(filename)

输出结果:

the file test.txt has about 12 words 

4、存储数据


很多程序要求用户输入某种信息,如让用户存储某些数据,程序需要把用户提供的数据存储在列表和字典等数据结构中,用户关闭程序时,数据需要被保存某个地方;最简单的方法就是使用json模块来存储数据;
JSON(javascript Object Notation)格式最初是为JavaScript开发的,随后成为了一周常见格式,被包含在Python的一个模块中;

4.1 使用json.dump()与json.load()

编写一个存储数字的简单程序,使用json.dump存储这组数字;

import json

numbers = [1,2,3,4,5,46,6,23,4,5,2,3]

filename = 'json.json'
with open(filename,'w') as fp:
    # 若目标文件不存在,写入模式会自动创建空白文件
    json.dump(numbers,fp)

输出结果:

# 打开json.json文件查看
[1, 2, 3, 4, 5, 46, 6, 23, 4, 5, 2, 3]

使用json.load()读取这组数字;

import json

filename = 'json.json'
with open(filename) as fp:
    numbers = json.load(fp)
print(numbers)

输出结果:

[1, 2, 3, 4, 5, 46, 6, 23, 4, 5, 2, 3]

4.2 保存和读取用户生成的数据

对于用户生成的数据,使用json保存将大有益处,如果不以某种方式存储数据,当程序执行结束或停止会丢失数据;
编写一个程序,输入用户名,将其保存至某个文件内;

import json

username = input("please input your name:")

filename = "username.json"
with open(filename,"w") as fp:
    json.dump(username,fp)
    print("we will remember you when you come back, " + username + " !")

输出结果:

"zxc"

编写一个程序,向被存储到文件的用户名发送一个信息;

import json

filename = 'username.json'
with open(filename,"r") as fp:
    username = json.load(fp)
    print("welcome back, " + username + " !")

输出结果:

welcome back, zxc !

将这两个程序结合起来,尝试从文件username.json获取用户名,若文件不存在,使用异常处理输入用户名,将其存储在username.json文件内,若文件存在则向文件内的用户名发送一个信息;

import json

filename = 'username.json'
try:
    with open(filename,"r") as fp:
        username = json.load(fp)
except FileNotFoundError:
    username = input("please input your name:")
    filename = "username.json"
    with open(filename, "w") as fp:
        json.dump(username, fp)
        print("we will remember you when you come back, " + username + " !")
else:
    print("welcome back, " + username + " !")

首先打开username.json文件,若文件存在,则读取文件内用户名,并执行else代码块,返回一个信息;若文件不存在,将引发FileNotFoundError异常,执行except代码块,需要输入一个用户名,创建文件并将其保存在文件内;

4.3 重构

代码能够正确运行,但是可以做进一步的改进,将代码划分为一些列完成具体工作的函数,这种过程称为重构;重构之后的代码更清晰、易于理解、容易扩展;
此处将上面的代码进行重构;

import json

def greet_user():
    filename = 'username.json'
    try:
        with open(filename, "r") as fp:
            username = json.load(fp)
    except FileNotFoundError:
        username = input("please input your name:")
        filename = "username.json"
        with open(filename, "w") as fp:
            json.dump(username, fp)
            print("we will remember you when you come back, " + username + " !")
    else:
        print("welcome back, " + username + " !")

if __name__ == '__main__':
    greet_user()

输出结果:

welcome back, zxc !

虽然使用了一个函数,但是这个函数中包含了太多了功能,需要将其功能分为不同函数进行执行,继续重构代码;

import json

# 函数-获取存储的用户名
def get_username():
    filename = 'username.json'
    try:
        with open(filename, "r") as fp:
            username = json.load(fp)
    except FileNotFoundError:
        # 不存在返回空
        return None
    else:
        # 存在返回文件内容
        return username

# 函数-校验文件内用户名是否存在
def greet_user():
    username = get_username()
    # 使用获取的用户名进行判断
    if username:
        # 用户名存在则发现信息
        print("welcome back, " + username + " !")
    else:
        # 用户名不存在,则创建用户名并保存到文件
        username = input("please input your name:")
        filename = "username.json"
        with open(filename, "w") as fp:
            json.dump(username, fp)
            print("we will remember you when you come back, " + username + " !")

if __name__ == '__main__':
    greet_user()

此处get_user函数中仍然存在多个功能,因此将功能提取到一个单独的函数中;

import json

def get_username(Python入门--18--异常与try,except语句

python 文件写入与储存

Python----文件和异常

python-异常&断言

Python:带有语句和异常处理

Python标准异常总结