Python编程 从入门到实践 第十章 文件和异常

本文详细介绍了如何使用Python进行文件读取,包括读取整个文件、逐行读取以及处理大型文件。同时,讨论了文件写入的方法,如写入空文件、追加内容。文章还深入探讨了异常处理,如ZeroDivisionError和FileNotFoundError,以及如何使用try-except代码块来确保程序的健壮性。最后,提到了使用json模块进行数据存储和读取的重要性。

1 从文件中读取数据

1.1 读取整个文件

  1. 函数open()返回一个表示文件的对象,Python将这个对象存储在我们在后面使用的变量中
  2. 关键字with在不再需要访问文件后将其关闭
  3. read()到达文件末尾时返回一个空字符串,将空字符串打印显示出来就是一个空行
  4. 演示示例如下:
with open('pi_digits.txt') as file_object:
    contents = file_object.read()
    print(contents.rstrip())
3.1415926535
  8979323846
  2643383279

1.2 文件路径

  1. open()只能打开与程序文件所属目录同级的文件,若是所属目录下一级或者其他目录等情况,将无法打开
  2. Windows系统中,文件路径使用反斜杠(\)而不是斜杠(/)
  3. 相对文件路径
  4. 绝对文件路径
  5. 绝对文件路径通常比相对路径更长,因此将其存储在一个变量中,再将该变量传递给open()
  6. 由于反斜杠在Python中被视为转义标记,为在Windows中确保万无一失,应在开头加上r
  7. 演示示例如下:
file_path =r'E:\GBB_01.技术\03、Python\002、Python编程从入门到实践\0001、Python操作\python_work\pi_digits.txt'
with open(file_path) as file_object:
    contents = file_object.read()
    print(contents.rstrip())
3.1415926535
  8979323846
  2643383279

1.3 逐行读取

  1. 要以每次一行的方式检查文件,可对文件对象使用for循环
  2. 演示示例如下:
filename = 'pi_digits.txt'
with open(filename) as file_object:
    for line in file_object:
        print(line.strip())
3.1415926535
8979323846
2643383279

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

  1. 使用关键字with时,open()返回的文件对象只在with代码块内可用
  2. 如果要在with代码块外访问该文件的内容,可在with代码块内部将文件的各行存储在一个列表中,并在with代码块外部使用该列表
  3. 演示示例如下:
filename = 'pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
for line in lines:
    print(line.rstrip())
3.1415926535
  8979323846
  2643383279

1.5 使用文件的内容

  1. 读取文本文件时,Python将其中的所有文本都解读为字符串。如果读取的是数字,并要将其作为数字使用,就必须使用函数int()将其转换为整数,或使用float()将其转换为浮点数
  2. 演示示例如下:
filename = 'pi_digits.txt'

with open(filename) as file_object:
    lines = file_object.readlines()

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

print(pi_string)
print(len(pi_string))
3.141592653589793238462643383279
32

1.6 包含一百万位的大型文件

  1. 对于可处理的数据量,Python没有任何限制,只要系统的内存足够多,想处理多少数据都可以
  2. 演示示例如下:
filename = 'pi_million_digits.txt'

with open(filename) as file_object:
    lines = file_object.readlines()

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

print(pi_string[:52] + "...")
print(len(pi_string))
3.14159265358979323846264338327950288419716939937510...
1000002

1.7 圆周率中包含你的生日吗

  1. 演示示例如下:
filename = 'pi_million_digits.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,in the form mmddyy: ")
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,in the form mmddyy: 120372
Your birthday appears in the first million digits of pi!

2. 写入文件

  1. 保存数据最简单的方式之一就是将其写入到文件中。通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出也依然存在

2.1 写入空文件

  1. 要将文本写入文件,在调用open()需要提供另一个实参
  2. open(文件名,‘r’) #读取模式打开这个文件
  3. open(文件名,‘w’) #写入模式打开这个文件
  4. open(文件名,‘a’) #附加模式打开这个文件
  5. open(文件名,‘r+’) #读取和写入模式打开这个文件
  6. open(文件名) #如果省略模式,那么默认按照只读模式打开文件
  7. 以写入模式(‘w’)打开文件时千万要小心,如果指定的文件里面已经有内容,那么程序运行完之后原有内容将被清空
  8. 演示示例如下:
filename = 'programming.txt'

with open(filename,'w') as file_object:
    file_object.write("I love programming.")

programming.txt
在这里插入图片描述
9. Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式
10.演示示例如下:

filename = 'programming.txt'

with open(filename,'w') as file_object:
    a = 123
    file_object.write(a)
Traceback (most recent call last):
  File "E:\GBB_01.技术\03、Python\002、Python编程从入门到实践\0001、Python操作\python_work\第10章 文件和异常.py", line 122, in <module>
    file_object.write(a)
TypeError: write() argument must be str, not int
  1. 修改后演示示例如下:
filename = 'programming.txt'

with open(filename,'w') as file_object:
    a = str(123)
    file_object.write(a)

programming.txt
可
可以看出str()转换为字符串格式后写入成功;
且由上面结果可知,原有txt文档中的内容 I love programming.被清空,返回当前结果 123

2.2 写入多行

  1. 函数write()不会在你写入的文本末尾添加换行符,如果你写入多行时没有指定换行符,结果会与你期望不符
  2. 演示示例如下:
filename = 'programming.txt'

with open(filename,'w') as file_object:
    file_object.write("I love programming.")
    file_object.write("I love creating new games.")

programming.txt

3. 要让每个字符串单独占一行,需要在write()语句中包含换行符
4. 演示示例如下:

filename = 'programming.txt'

with open(filename,'w') as file_object:
    file_object.write("I love programming.\n")
    file_object.write("I love creating new games.\n")

programming.txt

5. 还可以使用空格、制表符、空行来设置这些输出格式

2.3 附加到文件

  1. 如果要给文件添加内容,而不是覆盖原有内容,可以附加模式打开文件
  2. Python将你写入的文件行都添加到文件末尾
  3. 演示示例如下:
filename = 'programming.txt'

with open(filename,'a') as file_object:
    file_object.write("I also love finding meaning in large datasets.\n")
    file_object.write("I love creating apps that can run in a browser.\n")

programming.txt
在这里插入图片描述
可以看出,新写的两行代码添加到文件末尾

3. 异常

  1. Python使用被称为异常的特殊对象来管理程序执行期间发生的错误
  2. 每当程序运行发生错误时,程序运行将停止,显示一个traceback,其中包含有关异常的报告
  3. 异常可以使用 try-except 代码块进行处理,告诉Python发生异常时该怎么处理,程序也将继续运行,显示你编写友好的出错提示,而不是令人迷惑的traceback

3.1 处理ZeroDivisionError异常

  1. 演示示例如下
print(5/0)
Traceback (most recent call last):
  File "E:\GBB_01.技术\03、Python\002、Python编程从入门到实践\0001、Python操作\python_work\第10章 文件和异常.py", line 153, in <module>
    print(5/0)
          ~^~
ZeroDivisionError: division by zero
  1. 上面的 ZeroDivisionError 是一个异常对象

3.2 使用try-except 代码块

  1. 当你认为可能发生了错误时,可编写 try-except 代码块来处理可能发生的异常
  2. 演示示例如下:
try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")
You can't divide by zero!
  1. 如果 try-except 代码块后面还有其它代码,程序将接着运行

3.3 使用异常避免崩溃

  1. 发生错误时,如果程序中还有工作没有完成,妥善的处理错误尤其重要
  2. 例如在要求用户提供输入的程序中,如果程序能够妥善的处理无效输入,就能再提示用户输入有效输入,避免程序崩溃
  3. 下面这个程序没有采取任何处理错误的措施,因此在执行除数为0运算时,程序将崩溃
  4. 演示示例如下:
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)
Give me two numbers,and I'll divide them.
Enter 'q' to quit.

First number: 5
Second number: 0
Traceback (most recent call last):
  File "E:\GBB_01.技术\03、Python\002、Python编程从入门到实践\0001、Python操作\python_work\第10章 文件和异常.py", line 174, in <module>
    answer = int(first_number)/int(second_number)
             ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
ZeroDivisionError: division by zero

3.4 else代码块

  1. 通过将可能引发错误的代码放在 try-except 代码块中,可提高程序抵御错误的能力
  2. 依赖于try代码块成功执行的代码,放在else代码块中
  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: ")
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0!")
    else:
        print(answer)
Give me two numbers,and I'll divide them.
Enter 'q' to quit.

First number: 5
Second number: 0
You can't divide by 0!

First number: 5
Second number: 2
2.5

First number: q
  1. try-except-else 代码块的工作原理:只有可能引发异常的代码才需要放在try语句中
  2. 通过预测可能发生错误的代码,可编写健壮的程序

3.5 处理FileNotFoundError异常

  1. 使用文件时,一种常见的问题是找不到文件,可使用 try-except 代码块进行处理
  2. 下面演示示例中,程序尝试读取alice.txt的内容,但我故意没有将这个文件存储在当前文件所在的目录下
  3. 演示示例如下:
filename = 'alice.txt'

with open(filename) as f_obj:
    contents = f_obj.read()
Traceback (most recent call last):
  File "E:\GBB_01.技术\03、Python\002、Python编程从入门到实践\0001、Python操作\python_work\第10章 文件和异常.py", line 198, in <module>
    with open(filename) as f_obj:
         ^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
  1. 上述traceback 最后一行报告了 FileNotFoundError 异常
  2. 使用 try-except 代码块处理演示:
filename = 'alice.txt'

try:
    with open(filename) as f_obj:
        contents = f_obj.read()
except FileNotFoundError:
    msg = "Sorry,the file " + filename + " does not exist."
    print(msg)
Sorry,the file alice.txt does not exist.

3.6 分析文本

  1. 方法split()以空格为分隔符,将字符串拆分成多个部分,并将这些部分存储到一个列表中
  2. 演示示例如下:
>>> title = "Alice in Wonderland"
>>> title.split()
['Alice', 'in', 'Wonderland']

3.将alice.txt移动到程序文件当前目录下,让try 代码块能够成功执行
4.演示示例如下:

filename = 'alice.txt'

try:
    with open(filename) as file_obj:
        contents = file_obj.read()
except FileNotFoundError:
    msg = "Sorry,the file " + filename + " does not exist."
    print(msg)
else:
    # 计算文件大致包含多少个单词
    words = contents.split()
    num_words = len(words)
    print("The file " + filename + " has about " + str(num_words) + " words.")
The file alice.txt has about 29461 words.
  1. 定义函数进行演示:
def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as file_obj:
            contents = file_obj.read()
    except FileNotFoundError:
        msg = "Sorry,the file " + filename + " does not exist."
        print(msg)
    else:
        # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) +
              " words.")
filename = 'alice.txt'
count_words(filename)
The file alice.txt has about 29461 words.

3.7 使用多个文件

  1. 分析多个txt文件
  2. siddhartha.txt 没有放在程序运行文件的目录下
  3. 演示示例如下:
def count_words(filename):
	--snip--
	
filenames =['alice.txt','siddhartha.txt','moby_dict.txt','little_women.txt']
for filename in filenames:
    count_words(filename)
The file alice.txt has about 29461 words.
Sorry,the file siddhartha.txt does not exist.
The file moby_dict.txt has about 215136 words.
The file little_women.txt has about 189079 words.
  1. 使用try-except 代码块提供两个重要优点:
    避免让用户看到traceback;
    让程序能够继续分析能找到的其它文件

3.8 失败时一声不吭

  1. 并非每次捕到异常时都需要告诉用户,有时候希望一声不吭继续运行
  2. Python中有一个pass语句,可在代码块中使用让Python什么都不做
  3. 演示示例如下:
def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
		--snip--
    except FileNotFoundError:
        pass
    else:
		--snip--
filenames =['alice.txt','siddhartha.txt','moby_dict.txt','little_women.txt']
for filename in filenames:
    count_words(filename)
The file alice.txt has about 29461 words.
The file moby_dict.txt has about 215136 words.
The file little_women.txt has about 189079 words.
  1. 相比于前一个程序,在出现 FileNotFoundError 异常时,会执行except代码块,但什么都不会发生
  2. pass语句还充当了占位符,它提醒你在程序的某个地方什么都没做,并且以后也许要在这做些什么,比如上面这个例子,我们可能决定将找不到的文件名称写入到missing_files.txt中

3.9 决定报告哪些错误

  1. Python的错误处理结构让你能够细致的控制与用户分享错误信息的程度,要分享多少信息由你决定
  2. 编写的很好且经过详尽测试的代码不容易出现内部错误,如语法错误、逻辑错误
  3. 当程序依赖于外部因素,如用户输入、存在指定的文件、有网络连接,就有可能出现异常

4. 存储数据

  1. 很多程序要求用户输入某种信息,程序把用户提供的信息存储在列表和字典等数据结构,用户关闭程序时,你几乎都要保存他们提供的信息
  2. 使用模块json来存储数据
  3. JSON格式最初是为JavaScript开发的,随后成了常见格式,被包括Python在内的众多语言采用
  4. 是一种轻便格式,很有用,也易于学习

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

  1. 用json.dump()来将数据存储到指定的文件对象
  2. 用json.load()来将指定文件对象中的数据加载到内存
  3. json.dump(存储的数据,存储的文件对象)
  4. json.load(存储的文件对象)
  5. json.dump()演示示例如下:
import json

numbers = [2,3,5,7,11,13]
filename = 'numbers.json'
with open(filename,'w') as f_obj:
    json.dump(numbers,f_obj)

numbers.json

6. json.load()演示示例如下

import json

filename = 'numbers.json'
with open(filename) as f_obj:
    numbers = json.load(f_obj)
print(numbers)
[2, 3, 5, 7, 11, 13]

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

  1. 对于用户生成的数据,使用json保存它们大有裨益,因为如果不以某种方式进行存储,当程序停止运行时用户的信息将丢失
  2. 演示示例(存储用户名字)如下:
import json

username = input("What is your name? ")
filename = 'username.json'
with open(filename,'w') as f_obj:
    json.dump(username,f_obj)
    print("We'll remember you when you come back," + username + "!")
What is your name? Eric
We'll remember you when you come back,Eric!
  1. 演示示例(向名字被存储用户发出问候)如下:
import json

filename = 'username.json'
with open(filename) as f_obj:
    username = json.load(f_obj)
    print("Welcome back," + username + "!")
Welcome back,Eric!
  1. 扩展演示示例(上述功能合并)如下:
import json

# 如果以前存储了用户名,就加载它
# 否则,就提示用户输入用户名并存储它
filename = '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_obj:
        json.dump(username,f_obj)
        print("We'll remember you when you come back," + username + "!")
else:
    print("Welcome back," + username + "!")
Welcome back,Eric!
  1. 因为username.json文件中已经有Eric,所以上面扩展程序运行会输出Welcome back,Eric!

4.3 重构

  1. 定义:将代码划分为一系列完成具体工作的函数
  2. 作用:让代码更清晰、更易于理解、更容易扩展
  3. 演示示例如下:
import json

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

def get_new_username():
    """提示用户输入用户名"""
    username = input("What is your name? ")
    filename = '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 + "!")
    else:
        username = get_new_username()
        print("We'll remember you when you come back," + username + "!")

greet_user()
Welcome back,Eric!
  1. 上述演示示例中,每个函数都执行单一而清晰的任务
  2. 要编写出清晰而易于维护和扩展的代码,这种划分工作必不可少

5. 章节跳转

  1. Python编程 从入门到实践 第一章 起步
  2. Python编程 从入门到实践 第二章 变量和简单数据类型
  3. Python编程 从入门到实践 第三章 列表简介
  4. Python编程 从入门到实践 第四章 列表操作
  5. Python编程 从入门到实践 第五章 if语句
  6. Python编程 从入门到实践 第六章 字典
  7. Python编程 从入门到实践 第七章 用户输入和while循环
  8. Python编程 从入门到实践 第八章 函数
  9. Python编程 从入门到实践 第九章 类
  10. Python编程 从入门到实践 第十章 文件和异常
  11. Python编程 从入门到实践 第十一章 测试代码
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值