Loading

10 文件与异常

从文件中读取数据

一次性读取

# file_reader.py
with open('pi_digits.txt') as file_object:
    contents = file_object.read()
    print(contents.rstrip())
# 因为read() 到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行
# 要删除多出来的空行,可在print 语句中使用rstrip() 
# 相对路径:Linux OS X
with open('text_files/filename.txt') as file_object:
# 相对路径:Windows
with open('text_files\filename.txt') as file_object:
# 绝对路径:完整的路径
# 绝对路径通常比相对路径更长,因此将其存储在一个变量中,再将该变量传递给open() 会有所帮助
# 绝对路径:Linux OS X
file_path = '/home/ehmatthes/other_files/text_files/filename.txt'
with open(file_path) as file_object:
# 绝对路径:Windows
file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:

逐行读取

# file_reader.py
filename = 'pi_digits.txt'

with open(filename) as file_object:
    for line in file_object:
      print(line.rstrip())
# 因为在这个文件中,每行的末尾都有一个看不见的换行符,而print 语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自print 语句
# 要消除这些多余的空白行,可在print 语句中使用rstrip()

包含文件各行内容的列表

# 使用关键字with 时,open() 返回的文件对象只在with 代码块内可用
# 如果要在with 代码块外访问文件的内容,可在with 代码块内将文件的各行存储在一个列表中,并
# 在with 代码块外使用该列表
filename = 'pi_digits.txt'

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

for line in lines:
    print(line.rstrip())
filename = 'pi_30_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))
# 读取文本文件时,Python将其中的所有文本都解读为字符串。如果你读取的是数字,并要将其作为数值使用,就必须使用函数int() 将其转换为整数,或使用函数float() 将其转换为浮点数。

写入文件

# write_message.py
filename = 'programming.txt'

with open(filename, 'w') as file_object:
    file_object.write("I love programming.")
# 打开文件时,可指定读取模式 ('r' )、写入模式 ('w' )、附加模式 ('a' )或让你能够读取和写入文件的模式('r+' )
# 如果你省略了模式实参,Python将以默认的只读模式打开文件
# 如果你要写入的文件不存在,函数open() 将自动创建它
# 然而,以写入('w' )模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件
# Python只能将字符到串写入文本文件。要将数值数据存储文本文件中,必须先使用函数str() 将其转换为字符串格式
# 写入多行:函数write() 不会在你写入的文本末尾添加换行符
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")

附加模式可给文件添加内容,而不是覆盖原有的内容

异常

try-except-else 代码块的工作原理大致如下:
Python尝试执行try 代码块中的代码;
只有可能引发异常的代码才需要放在try 语句中;
有时候,有一些仅在try 代码块成功执行时才需要运行的代码,这些代码应放在else 代码块中;
except 代码块告诉Python,如果它尝试运行try 代码块中的代码时引发了指定的异常,该怎么办

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")
# division.py
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)

split():以空格为分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中

title = "Alice in Wonderland"
title.split()

# ['Alice', 'in', 'Wonderland']

分析文本

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)
else:
# 计算文件大致包含多少个单词
    words = contents.split()
    num_words = len(words)
    print("The file " + filename + " has about " + str(num_words) + " words.")
# word_count.py
def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as f_obj:
            contents = f_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.")

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
    count_words(filename)

要让程序在失败时一声不吭,可像通常那样编写try 代码块,但在except 代码块中使用pass 语句;
pass 语句还充当了占位符,它提醒你在程序的某个地方什么都没有做,并且以后也许要在这里做些什么

存储数据

JSON(JavaScript Object Notation)

# number_writer.py
import json

numbers = [2, 3, 5, 7, 11, 13]

filename = 'numbers.json'
with open(filename, 'w') as f_obj:
    json.dump(numbers, f_obj)
# number_reader.py
import json

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

print(numbers)
# remember_me.py
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 + "!")
# greet_user.py
import json

filename = 'username.json'

with open(filename) as f_obj:
    username = json.load(f_obj)
    print("Welcome back, " + username + "!")
# 前两个代码合并
# remember_me.py
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 + "!")

重构

重构:代码能够正确地运行,但可做进一步的改进——将代码划分为一系列完成具体工作的函数,重构让代码更清晰、更易于理解、更容易扩展

# remember_me.py
import json

def greet_user():
    """问候用户,并指出其名字"""
    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 + "!")

greet_user()

重构

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 greet_user():
    """问候用户,并指出其名字"""
    username = get_stored_username()
    if username:
        print("Welcome back, " + username + "!")
    else:
        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 + "!")

greet_user()

重构

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()

在remember_me.py的这个最终版本中,每个函数都执行单一而清晰的任务;
要编写出清晰而易于维护和扩展的代码,这种划分工作必不可少。

小结

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

posted @ 2023-04-20 17:18  Artwalker  阅读(11)  评论(0编辑  收藏  举报
Live2D