17 文件与异常处理

文中需要的所有程序和文件可从-->This is a llink下载

本文主要从以下三点展开 :

①文件的读取 ②异常的处理 ③数据的简单操作


一、文件的读取 --- with open(file_name / file_path) as f_obj:
读取方式上可分为按文件名读取和按文件路径读取两种方式。
  • 按文件名读取 --- file_name = 'Alice.txt'
file_name = 'Alice.txt'

with open(file_name) as f_obj:   # f_obj是file_object的简写
    contents = f_obj.read()      #file.read()表示读取文件file的内容
    print(contents)
  • 按文件路径读取 --- file_path = 'home/PythonSudy/Alice.txt
file_path = 'home/PythonSudy/Alice.txt'

with open(file_path) as f_obj:
      contents = f_obj.read()
      print(contents)
也可以逐行读取文件里的内容
  • 逐行读取文本文件内容 --- for line in f_obj:
file_name = 'pi_digits.txt'

with open(file_name) as file_object:
    for line in file_object:
        print(line)
  • 创建一个各行内容的列表 --- .readlines()
file_name = 'pi_digits.txt'

with open(file_name) as file_object:
    lines = file_object.readlines() 
# readlines()函数创建一个读取的列表

for line in lines:   
    print(line)
# 注意for循环已在with open as代码块以外,这是因为readlines()函数的允许
一个关于π的程序 --- 你的生日是否在 π 的前100万位中
# 使用读取的文件 --- 将读取结果显示成一行
file_name = 'pi_million_digits.txt'

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

pi_string = ''                   # 先创建一个空字符
for line in lines:
    pi_string += line.strip()    # 累加读取的字符串列表(去除末尾的空字符)

print(pi_string[:52] + "...")    # 读取列表前52项
print(len(pi_string))            # len()函数显示字符串长度

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.")

下面我们来尝试写入(更改文件内容) --- .write()

  • 覆盖原文件内容写入 --- 写入模式 ‘w’
filename = 'programming.txt'

with open(filename, 'w') as file_object:       # 以写入模式‘w’打开文件
    file_object.write("I love programming!\n") # 用write()函数开始写入
    #以写入模式运行时要特别注意,写入后只保留新写入的内容,擦除以前的内容

    file_object.write("I love creating new games!\n")
    #打开programming文件有时会发现新写入的内容挤在一行,我们需要注意加换行符
    file_object.write("I love Python!\n")
  • 不覆盖原文件内容 --- 附加模式 ‘a’
#如果要是给文件添加内容而不是覆盖,可以使用附加模式'a'打开
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 creatinng apps that can run in a browser.\n")
  • 只读模式打开 --- 只读模式 ‘r’

至此,学习了文件的基本读写,进一步的文件处理放在最后。

下面我们先学习另一个有趣的问题 —— 发生异常时如何处理。


异常处理 --- try: ... except ... else: ...

  • 一个最常见的异常 --- 除 0 错误
#两个数的除法 --- 除数是0时自动提醒
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
    #将可能引发错误的代码放在try-except代码块中
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by zero!")
    #如果try-except代码块中没有错误,将自动跳过这except这一段
    else:
        print(answer)

异常处理的代码块儿是try -except或者try-except-else当程序运行到try-except代码块时先执行try下的内容,若有错误则执行except下的内容;若没有错误则跳过except下面的内容( 有else则执行else下的内容 )除 0 错误的标记是ZeroDivisionError —— except ZeroDivisionErroe:


  • 文件读取失败异常 --- 找不到指定的文件名
# 假设查看一个目录下不存在的文件aliceX.txt --- 设置相应的反馈信息
filename = 'aliceX.txt' # 这个文件压根不存在

try:
    with open(filename) as f_obj:
        contents = f_obj.read()
except FileNotFoundError:
    msg = "Sorry, the file " + filename + " does not exist."
    print(msg)
# 执行 try 下的内容,若无法正常执行就返回 except 下的内容(except需要指定错误类型)

文件读取异常的标记是 FileNoFoundError

其他错误标记可以通过其名称直接明白其含义,本文不再多提。

但是有时候就算程序出现意料之中的异常,也不需要做什么

例如读取一组文件时失败了一个,想让程序继续执行下去即可
return None or pass
# 编写一个计算文件含有多少个单词的函数 --- .split()函数

def count_words(filename):
    """计算一个文件大概包含多少个单词"""
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:          # ’找不到文件‘错误提醒功能
    #   print("No file name " + filename)
        pass
    else:
        # 计算文件大概包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) + " words.")

# 下面开始调用这个函数 --- 可以是多个文件的文件名列表
filenames = ['alice.txt', 'little_women.txt', 'moby_dict.txt', 'siddhartha']
# 注意最后一个故意未加.txt让程序找不到文件
for filename in filenames:
    count_words(filename)
# 结果可以看到,moby_dict.txt文件不存在 --- 并且提示了信息。

# 但是有时候我们偏偏就不想让Python提醒这种”错误“ --- 失败时一声不吭。
# 在 try-except 中插入 pass 或者 return None 即可。

文中的split( )函数的作用是计算文件含有多少个字符


下面我们来进一步使用文件 --- 存储文件和加载文件json模块

  • 创建一个数字列表文件并存储 --- json.dump( )
# 创建一个.json文件并存入一个数字列表 --- json.dump( )

import json
# 导入json模块,使用其中的json.dump() --- 存储一组数;json.load() --- 将内容读取到内存中

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

filename = 'numbers.json'           # 一般将使用的文件扩展名为.json来指明文件存储的数据为JSON格式的
with open(filename, 'w') as f_obj:  # 我们以写入模式打开(或者创建)一个number.json的文件
     json.dump(numbers, f_obj)      # 用json.dump将列表内容写入f_obj(也就是number.json)

# 运行后会发现已经创建了一个叫 number.json 的文件,其中的内容是列表[2, 3, 5, 7, 11, 13]
# 要查看文件里的内容还需要json.load()函数将内容读取到内存中,见程序number.reader.py

  • 读取json文件 --- json.load( )
# 读取json文件并显示内容 --- json.load()

import json

file_name = 'numbers.json'
with open(file_name) as f_obj: # 还是先打开
    numbers = json.load(f_obj) # 然后将文件内容加载到内存 --- json.load()

print(numbers)
  • 利用json模块的例子 --- 记住用户登录信息
import json

def get_store_username():
    """如果存储了用户名,就获取它"""
    filename = 'username.json'
    try:
        with open(filename) as f_obj:
            username = json.load(f_obj)
    except FileNotFoundError: # 若不存在,什么也不做(顺序执行) --- return None
        return None
    else:
        return username       # 否则就返回用户名

def get_new_username():
    """提示用户输入用户名"""
    username = input("What's your name?")
    filename = 'username.json'
    with open(filename, 'w') as f_obj:
        json.dump(username, f_obj)  # 将username写入f_obj中
    return username

def greet_user():
    """问候用户,并指出其名字"""
    username = get_store_username() # 调用以上函数获取用户名
    if username:                    # 直接if username判断是否获取到
        print("Welcome back, " + username + "!")
    else:
        username = get_new_username()
        print("We'll remember you when you come back, " + username + "!")

# 下面直接调用函数greet_user()
greet_user()

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


下面是书后的一个小练习 ---- 记住你最喜欢的数字O(∩_∩)O

  • 首先是小程序段 favourite_number.pyremember_number.py
import json

number = input("Which number do you like best?")
filename = 'favourite_number.json'
with open(filename, 'w') as f_obj:
    json.dump(number, f_obj) # 将读取到的number信息写入f_obj中
import json

filename = 'favourite_number.json'
with open(filename) as f_obj:
    number = json.load(f_obj)  # 将读取到的f_obj内容写入内存
    print("I konw your favourite number! It's " + number + ".")

注意程序必须在同一工程目录下才可相互调用

  • 最终的完整程序 --- guess_number.py
import json

def get_store_favourite_number():
    """如果已经存储了数字,就获取它"""
    filename = 'favourite_number.json'
    # 试着打开相应的文件,若不存则返回空值None;存在就返回该文件的内容number
    try:
        with open(filename) as f_obj:
            number = json.load(f_obj)
    except FileNotFoundError:
        return None
    else:
        return number

def get_new_favourite_number():
    """获取用户输入的数字"""
    number = input("Which number do you like best?")
    filename = 'favourite_number.json'
    with open(filename, 'w') as f_obj:
        json.dump(number, f_obj)  # 将读取到的number信息写入f_obj中


def guess_result():
    """显示用户刚才输入的数字"""
    number = get_store_favourite_number()
    if number:
        print("I konw your favourite number! It's " + number + ".")
    else:
        get_new_favourite_number()
        print("I can get which is your favorite number next!")

# 下面调用函数guess_result()
# 如果文件favourite_number.json存在就直接显示结果;不存在就再问一次
guess_result()


最后附一张第10章内容的总结图(来自Xmind)

第 10 章 文件和异常(总结).png

一转眼又快过年了,再次祝大家猪年大吉 ! (* ̄(oo) ̄)

240489918.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271