Python-11.1-文件和异常

文件和异常

  • 将学习处理文件,让程序能够快速地分析大量的数据
  • 将学习错误处理,避免程序在面对意外情形时崩溃
  • 将学习异常,它们是Python创建的特殊对象,用于管理程序运行时出现的错误
  • 将学习模块json,它让你能够保存用户数据,以免在程序停止运行后丢失
     
     
  • 提高程序的适用性、可用性和稳定性
  • 学习处理文件和保存数据可让你的程序使用起来更容易:
    • 用户将能够选择输入什么样的数据,以及在什么时候输入
    • 用户使用你的程序做一些工作后,可将程序关闭,以后再接着往下做
       
       
  • 学习处理异常:
    • 应对文件不存在的情形,以及处理其他可能导致程序崩溃的问题
    • 能让程序再面对错误的数据时更健壮

一:从文件中读取数据

  • 文本文件可存储的数据量多得难以置信:天气数据、交通数据、社会经济数据等
  • 每当需要分析或修改存储在文件中的信息时,读取文件都很用,对数据分析应用程序来说尤其重要
  • 可以编写这样的程序
    • 读取一个文本文件的内容,重新设置这些数据的格式并将其写入文件,让浏览器能够显示这些内容
  • 要使用文本文件的信息,首先需要将信息读取到内存中

1、读取整个文件

  • 在G盘文件夹qwh下创建一个名为qaz.txt的文档文件
  • 关键字with在不再需要访问文件后将其关闭
  • 函数open()接受一个参数:要打开的文件名称
  • 函数read()读取这个文件的全部内容
# 函数open()返回一个表示文件的对象
with open(r'G:\qwh\qaz.txt') as file_object:
    contents = file_object.read()
    print(contents.strip())

3.1415926353
8979323846
2643383279

3、逐行读取

  • 读取文件时,常常需要检查其中的每一行
    • 在文件中查找特定的信息
    • 以某种方式修改文件中的文本
  • 要以每次一行的方式检查文件,可对文件对象使用for循环
filename = 'G:\qwh\qaz.txt'
with open(filename) as file_object:
    for line in file_object:
        print(line)

# 出现空白的原因是
# 在文件中每行的末尾都有一个转行符
# 可在print与剧中使用rstrip()

3.1415926353

8979323846

2643383279

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

  • 使用关键字with时,open()返回的文件对象只在with代码块内使用
  • 如果要在代码块外使用该列表:
    • 可在with代码块内将文件的各行存储在一个列表中
    • 并在with代码块外使用该列表
filename = 'G:\qwh\qaz.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
    
for line in lines:
    print(line.rstrip())

3.1415926353
8979323846
2643383279

5、使用文件的内容

  • 将文件读取到内存后,就可以以任何方式使用这些数据了
  • 使用圆周率的值
    • 创建一个字符串,它包含文件中存储的所有数字,且没有任何空格
  • 注意:
    • 读取文本文件时,Python将其中的所有文本都解读为字符串
    • 如果读取的是数字,并要将其作为数值使用,就必须使用函数int()
    • 或使用函数float()将其转换为浮点数
filename = 'G:\qwh\qaz.txt'
with open(filename) as file_object:
    lines = file_object.readlines()

pi_string = ''
for line in lines:
    pi_string += line.strip()
    
print(pi_string)

3.141592635389793238462643383279

a = '8.5'
a = float(a)
a = int(a)
if a > 0:
    print(a)

8

6、包含一百万位的大型文件

  • 如果有一个文本文件,其中包含精确到小数点后1000000位而不是30位的圆周率,也可以创建一个包含所有这些数字的字符串
  • 只需将这个文件传递给它即可
filename = 'G:\qwh\qaz_million.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
    
pi_string = ''
for line in lines:
    pi_string += line.strip()
    
print(pi_string[:10])
print(len(pi_string))

3.14159263
9912

7、圆周率中包含你的生日吗

filename = 'G:\qwh\qaz_million.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
    
pi_string = ''
for line in lines:
    pi_string += line.strip()
    
birthday = input("Enter your birthday:")
if birthday in pi_string:
    print("Your birthday appears in the first million digits of pi!")
else:
    print("Your birthday does not appear in the first million digits of pi.")

Enter your birthday:961006
Your birthday does not appear in the first million digits of pi.

二:写入文件

  • 保存数据的最简单的方式之一是将其写入到文件中
  • 通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出也依然存在
    • 可以在程序结束运行后查看这些输出
    • 可与别人分享输出文件
    • 可编写程序来将这些输出读取到内存中并进行处理

1、写入空文件

  • 要将文本写入文件,在调用open()时需提供另一个实参,告诉Python要写入打开的文件
  • 调用open()提供两个参数
    • 第一个实参是要打开的文件名称
    • 第二个实参(‘w’)告诉Python以写入模式打开这个文件
  • 打开文件时,可指定
    • 读取模式(‘r’)
    • 写入模式(‘w’)
    • 附加模式(‘a’)
    • 读取和写入文件模式(‘r+’)
    • 如果省略了模式实参,Python将以默认的只读模式打开文件
  • 注意:
    • 如果写入的文件不存在,函数open()将自动创建
    • 以写入(‘r’)模式打开文件时,如果指定的文件已经存在,Python将在返回文件对象前清空该文件
    • Python只能将字符串写入文本文件
      • 要将数值数据存入到文本文件中,必须先使用函数str()将其转换为字符串格式
# 写入文件案例
file_name = 'G:\qwh\programming.txt'
with open(file_name, 'w') as file_object:
    file_object.write("I am superman.")
# 将数值数据转换成字符串写入文本文件
file_name = 'G:\qwh\int.txt'
a = 123
with open(file_name, 'w') as file_object:
    file_object.write(str(a))

2、写入多行

  • 函数write()不会在你写入的文本末尾添加换行符
# version1.0

file_name = 'G:\qwh\programming.txt'

with open(file_name, 'w') as file_object:
    file_object.write('I like apple.')
    file_object.write('I like banana.')
    file_object.write('I like pear.')
# version2.0

file_name = 'G:\qwh\programming.txt'
apple = 'I like apple.\n'
banana = 'I like banana.\n'
pear = 'I like pear.\n'

with open(file_name, 'w') as file_object:
    file_object.write(apple + banana + pear)

3、附加到文件

  • 要给文件添加内容,而不是覆盖原有的内容,可以附加模式打开文件
  • 以附加模式打开文件时,Python不会返回文件对象前清空文件,而你写入到文件的行都将添加到文件末尾哦
  • 如果指定的文件不存在,Python将为你创建一个空文件
file_name = 'G:\qwh\programming.txt'
fruits = "I like this fruit very much."
with open(file_name, 'a') as file_object:
    file_object.write(fruits)

三:异常

  • Python使用被称为异常的特殊对象来管理程序执行期间发生的错误
  • 每当发生让Python不知所措的错误时,它都会创建一个异常对象
    • 如果你编写了处理该异常的代码,程序将继续运行
    • 如果你未对异常进行处理。程序将停止,并显示一个traceback,其中包含有关异常的报告
  • 异常是使用try-except代码块处理的
    • try_except代码块让Python执行指定的操作,同时告诉Python发生异常时该怎么办
    • 使用了try-except代码块时,即便出现异常,程序也将继续运行
      • 显示你编写的友好的错误信息,而不是令用户迷惑的traceback

1、处理ZeroDivisionError异常

  • Python无法按要求做时,就会创建一个ZeroDivisionError异常对象
  • Python将停止运行程序,并指出引发了哪种异常,而我们可根据这些信息对程序进行修改
    • 如果再次发什么这样的错误,就有备无患了

2、使用try-except代码块

  • 可编写一个try-except代码块来处理可能引发的异常
    • 让Python尝试运行一些代码,并告诉它如果这些代码引发了指定的异常,该怎么办
  • 如果try-except代码块后面还有其他代码,程序将接着运行
try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")
print(5/2)

You can’t divide by zero!
2.5

3、使用异常避免崩溃

  • 发生错误时,如果程序还有工作没有完成,妥善地处理错误尤其重要
# 只执行除法运算的简单计算器
# 此程序未采取任何处理错误的措施
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit")

while True:
    first_number = input("\nFirst number:")
    if first_number == 'q':
        break
    second_number = input("Second number:")
    if second_number == 'q':
        break
    answer = int(first_number) / int(second_number)
    print(answer)

4、else代码块

  • 通过将可能引发错误的代码放在try-except代码块中,可提高这个程序抵御错误的能力
  • 将可能引发错误的代码放在try代码块中
  • 依赖于try代码块成功执行的代码都放在self代码块中
  • except代码块当try代码块中的代码发生指定异常时将告诉Python如何处理
# 采取处理错误的措施
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit")

while True:
    first_number = input("\nFirst number:")
    if first_number == 'q':
        break
    second_number = input("Second number:")
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0.")
    else:
        print(int(answer))

Give me two numbers, and I’ll divide them.
Enter ‘q’ to quit

First number:6
Second number:3
2

First number:6
Second number:0
You can’t divide by 0.

First number:q

5、处理FileNotFound异常

  • 使用文件时,一种常见的问题是找不到文件
    • 查找的文件在其他地方
    • 文件名可能不正确或者文件根本不存在
  • 可以使用try-except代码块以直观的方式进行处理
# FileNotFound异常
file_name = r'G:\qwh\dsa.txt'

try:
    with open(file_name) as file_object:
        contents = file_object.read()
except FileNotFoundError:
    msg = "Sorry, the file " + file_name + " does not exist."
    print(msg)
else:
    print(contents)

Sorry, the file G:\qwh\dsa.txt does not exist.

6、分析文本

  • 分析文本文件,尝试计算它包含多少个单词
  • 使用方法split()
    • 以空格分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中
    • 结果是一个包含字符串中所有单词的列表。虽然有些单词可能包含标点
file_name = r'G:\qwh\programming.txt'

try:
    with open(file_name) as file_object:
        contents = file_object.read()
except FileNotFoundError:
    msg = "Sorry, the file " + file_name + " does not exist."
    print(msg)
else:    
    words = contents.split()
    num_words = str(len(words))
    print("The file " + file_name + " has about " + num_words + " words.")

The file G:\qwh\programming.txt has about 120 words.

7、使用多个文件

  • 分析多个文件时,可将这个程序的大部分代码移到一个名为count_words()函数中
  • try-except代码块提供了两个重要的优点
    • 避免用户看到tracebook
    • 让程序能够继续分析能找到的其他文件
def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as file_object:
            contents = file_object.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + file_name + " does not exist."
        print(msg)
    else:
        words = contents.split()
        num_words = str(len(words))
        print("The file " + file_name + " has about " + num_words + " words.")

filenames = [r"G:\qwh\programming.txt", r"G:\qwh\tgb.txt", r"G:\qwh\favorite.txt"]
for filename in filenames:
    count_words(filename)
    print("\n")

The file G:\qwh\programming.txt has about 120 words.

Sorry, the file G:\qwh\programming.txt does not exist.

The file G:\qwh\programming.txt has about 336 words.

8、失败时一声不吭

  • 并非每次捕获到异常都需要告诉用户
    • 可使用语句pass,充当占位符,表示什么都不做
def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as file_object:
            contents = file_object.read()
    except FileNotFoundError:
        pass
    else:
        words = contents.split()
        num_words = str(len(words))
        print("The file " + filename + " has about " + num_words + " words.")

filenames = [r"G:\qwh\programming.txt", r"G:\qwh\tgb.txt", r"G:\qwh\favorite.txt"]
for filename in filenames:
    count_words(filename)
    print("\n")

The file G:\qwh\programming.txt has about 3 words.

The file G:\qwh\favorite.txt has about 336 words.

四:存储数据

  • 很多程序都要求用户输入某种信息,如让用户存储游戏首选项或提供要可视化的数据
    • 程序都把用户提供的信息存储在列表和字典等数据结构中
  • 一种简单的方式是使用json来存储数据
    • 模块json让你能够将简单的Python数据结构存储到文件中,并在程序再次运行时加载该文件中的数据

1、使用 json.dump() 和 json.load()

  • 函数 json.dump() :
    • 将数据结构存储到文件中
    • 接受两个实参:
      • 要存储的数据
      • 可用于存储数据的文件对象
  • 函数 json.load() :
    • 将数据读取到内存中
    • 接受一个实参:
      • 可用于存储数据的文件对象
  • 通常使用文件扩展名.json来指出文件存储的数据为JSON格式
# json.dump()
import json

numbers = [1, 5, 9, 8, 4, 2, 6, 7]

filename = r"G:\qwh\number.json"
with open(filename, 'w') as f_obj:
    json.dump(numbers, f_obj)
# json.load()
import json

filename = r"G:\qwh\number.json"

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

[1, 5, 9, 8, 4, 2, 6, 7]

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

  • 对于生成的数据,使用json保存它们大有裨益
    • 程序停止运行时用户的信息将会保存下来而不会丢失
# 1、保存数据
import json

username = input('Whis is your name?')

filename = r'G:\qwh\username.json'
with open(filename, 'w') as f_obj:
    # 将用户名和一个文件对象传递给它
    json.dump(username, f_obj)
    print("We'll remember you when you come back, " + username.title() + ".")

Whis is your name?jack
We’ll remember you when you come back, Jack.

# 2、读取数据
import json

filename = r"G:\qwh\username.json"

with open(filename) as f_obj:
    username = json.load(f_obj)
    print("Welcome back, " + username + ".")

Welcome back, jack.

# 3、当读取的数据不存在时

import json

# 如果以前存储了用户名,就加载它
# 否则,就提示用户输入用户名并存储它

filename = r"G:\qwh\username.json"

try:
    with open(filename) as f_obj:
        username = json.load(f_obj)
except FileNotFoundError:
    username = input("Whis is your name?")
    with open(filename, 'w') as f_obj:
        json.dump(username, f_obj)
        print("We'll remember you when you come back, " + username.title() + ".")
else:
    print("Welcome back, " + username.title() + ".")

Welcome back, Jack.

3、重构

  • 将代码划分为一系列完成具体工作的函数,这样的过程被称为重构
    • 重构让代码更清晰、更易于理解、更容易扩展
  • 要重构,可将其大部分逻辑放到一个或多个函数中
# version1.0
import json

def greet_user():
    """问候用户,并指出其名字"""
    
    filename = r"G:\qwh\username.json"
    
    try:
        with open(filename) as f_obj:
            username = json.load(f_obj)
    except FileNotFoundError:
        username = input("What is your name?")
        with open(filename, 'w') as f_object:
            json.dump(username, f_obj)
            print("We'll remember you when you come back, " + username.title() + ".")
    else:
        print("Welcome back, " + username.title() + ".")
greet_user()

Welcome back, Jack.

# version2.0
import json

def get_stored_username():
    """如果存储了用户名,就获取它"""
    
    filename = r"G:\qwh\username.json"
    
    try:
        with open(filename) as f_obj:
            username = json.load(f_obj)
    except FileNotFoundError:
        return None
    else:
        return username
    
def greet_user():
    """问候用户指出名字"""
    username = get_stored_username()
    if username:
        print("Welcome back, " + username.title())
    else:
        username = input("What is your name?")
        filename = r"G:\qwh\username.json"
        with open(filename, 'w') as f_obj:
            json.dump(username, f_obj)
            print("We'll remember you when you come back, " + username.title() + ".")
            
greet_user()

Welcome back, Jack

  • 最终版本中,每个函数都执行单一而清晰的任务
  • 当我们调用greet_user(),它打印一条合适的消息
    • 要么欢迎老用户回来
    • 要么问候新用户
  • 为此,它首先调用get_stored_username(),这个函数只负责获取存储的用户名(如果存储的话)
  • 再在必要时调用get_new_username(),这个函数只负责获取并存储新用户的用户名
  • 要编写除清晰而易于维护和扩展的代码,这种划分工作必不可少
# version3.0
import json

def get_stored_username():
    
    """如果存储了用户名,就获取它""" 
    filename = r"G:\qwh\username.json"
    
    try:
        with open(filename) as f_obj:
            username = json.load(f_obj)
    except FileNotFoundError:
        return None
    else:
        return username
    
def greet_new_username():

    """提示用户输入名字"""
    username = input("What is your name?")
    
    filename = r"G:\qwh\username.json"
    with open(filename, 'w') as f_obj:
        json.dump(username, f_obj)
    return username

def greet_user():
    """问候用户,并指出其名字"""
    username = get_stored_username()
    if username:
        print("Welcome back, " + username.title() + ".")
    else:
        username = greet_new_username()
        print("We'll remember you when you come back, " + username.title() + ".")
        
greet_user()

Welcome back, Jack

五:小结

  • 如何使用文件
  • 如何一次性读取整个文件,以及如何以每次一行的方式读取文件的内容
  • 如何写入文件,以及如何将文本附加到文件末尾
  • 什么是异常以及如何处理程序可能引发的异常
  • 如何存储Python数据结构,以保存用户提供的信息,避免用户每次运行程序都需要重新提供
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值