Python文件与异常之存储数据

存储数据

很多程序都要求用户输入某种信息,如让用户存储游戏首选项或提供要可视化的数据。不管专注的是什么,程序都把用户提供的信息存储在列表和字典等数据结构中。用户关闭程序时,你几乎总是保存他们提供的信息:一种简单的方式是使用模块json来存储数据。
模块json让你能够将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据,还可以使用json在Python程序之间分享数据。更重要的是,JSON数据格式并非Python专用的,这样能够将以JSON格式存储的数据与使用其他编程语言的人分享。这是一种非常轻便格式,很有用,也易于学习。
注:JSON(JavaScript Object Notation)格式最初是为JavaScript开发的,但随后成了一种常见格式,被包括Python在内的众多语言采用。

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

来编写一个存储一组数字的简短程序,再编写一个将这些数字读取到内存中的程序。第一个程序将使用json.dump()来存储这组数字,而第二个程序将使用json.load()。
**函数json.dump()**接受两个实参:要存储的数据以及可用于存储数据的文件对象。来举例如何使用json.dump()来存储数字列表:
number_writer.py

import json
#导入Json模块

#创建一个数字列表
numbers = [2,3,5,7,11,13]

#创建一个存储数据的json文件
filename = 'numbers.json'
with open(filename,'w') as f_obj:
	json.dump(numbers,f_obj)

output:是输出到以.json结尾的文件中
在这里插入图片描述
下面再把文件中的内容读取到内存中

import json
#导入Json模块

filename = 'numbers.json'
try:
    with open(filename) as f:
        numbers = json.load(f)
    print(numbers)
except FileNotFoundError:
    pass
[2, 3, 5, 7, 11, 13]

这是程序之间共享数据的一种方式。

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

对于用户生成的数据,使用json保存它们大有裨益,因为如果不以某种方式进行存储,等程序停止运行时用户的信息将丢失。下面举个例子:用户首次运行程序时被提示输入自己的名字,这样再次运行程序时就记住它了。
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("Welcom back, " + username + "!")

output:

Welcom back, aaron!

接下来需要把两个程序合并到一个程序中,合并到remember_me.py中。在程序运行时,我们将尝试从文件username.json中获取用户名,因此我们首先编写一个尝试恢复用户名的try代码块。如果这个文件不存在,我们就在except代码块中提示用户输入用户名,并将其存储在username.json中,以便程序再次运行时能够获取它:
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 + "!")
Welcome back, aaron!

在这里有个问题,如果要分享的文件在,但是里面的内容为空,就会在load的时候,返回空的文件对象,这个时候会出错,大家想想该怎么处理这样的异常呢?

3.重构

有的时候我们会遇到这样的情况,是什么呢?就是代码能够正确的运行,但可做进一步的改进-----将代码划分为一系列完成具体工作的函数,这样的过程称为重构重构是为了让代码更清晰,更易于理解,更容易扩展。
比如重构一下remember_me.py,remember_me.py重点是问候用户,因此将其代码都放到一个名为greet_user()的函数中:

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

把之前生成的username.json文件给删除,然后再次运行代码,结果如下:

What is your name? aaron
We'll remember you when you come back, aaron!

虽然把代码移到了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:
        uername = imput("What is your name? ")
        filename = 'username.json'
        with open(filename,'w') as f_obj:
            json.dump(username,f_obj)
            print("We'll remember your when you combe back, " + username + "!")


greet_user()
Welcome back, aaron!

注:在编写这段代码的时候,出现一个不愉快的小插曲,使用的编辑调试工具时vscode+win python3,在编译到greet_user函数的username行总是报错误:_file
code = compile(f.read(), fname, ‘exec’)
username = get_stored_username()
^
IndentationError: unindent does not match any outer indentation level,说是“不匹配任何外部缩进级别”,重写代码也不行,怎么解决的呢,就是把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:
        get_new_username()
        print("We'll remember your when you combe back, " + username + "!")


greet_user()
Welcome back, aaron!

练习:
favorite_number_write.py:

import json

number = input("What's your favorite number? ")

with open('favorite_number.json', 'w') as f:
    json.dump(number, f)
    print("Thanks! I'll remember that.")
What's your favorite number? 42
Thanks! I'll remember that.

favorite_number_read.py:

import json

with open('favorite_number.json') as f:
    number = json.load(f)

print("I know your favorite number! It's " + str(number) + ".")
I know your favorite number! It's 42.

练习:

import json

try:
    with open('favorite_number.json') as f:
        number = json.load(f)
except FileNotFoundError:
    number = input("What's your favorite number? ")
    with open('favorite_number.json', 'w') as f:
        json.dump(number, f)
    print("Thanks, I'll remember that.")
else:
    print("I know your favorite number! It's " + str(number) + ".")
第一次运行时的输出:

What's your favorite number? 42
Thanks, I'll remember that.
第二次运行的输出:

I know your favorite number! It's 42.

练习10-13 验证用户
最后一个remember_me.py版本假设用户要么已输入其用户名,要么是首次运行该程序。我们应修改这个程序,以应对这样的情形:当前和最后一次运行该程序的用户并非同一个人。
为此,在greet_user()中打印欢迎用户回来的消息前,询问他用户名是否是对的。如果不对,就调用get_new_username()让用户输入正确的用户名。

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:
    	correct = input("Are you " + username + "? (y/n) ")
        if correct == 'y':
            print("Welcome back, " + username + "!")
        else:
            username = get_new_username()
            print("We'll remember you when you come back, " + username + "!")
    else:
        username = get_new_username()
        print("We'll remember you when you come back, " + username + "!")

greet_user()
> python verify_user.py
What is your name? eric
We'll remember you when you come back, eric!

> python verify_user.py
Are you eric? (y/n) y
Welcome back, eric!

> python verify_user.py
Are you eric? (y/n) n
What is your name? ever
We'll remember you when you come back, ever!

> python verify_user.py
Are you ever? (y/n) y
Welcome back, ever!

你可能注意到了,在这个版本的greet_user()中,有两个相同的else代码块。要整理这个函数,一种方法是使用空的return语句。空的return语句让Python离开当前函数,不执行后面的代码。
下面的greet_user()版本更清晰的:

def greet_user():
    """基于用户名问候用户。"""
    username = get_stored_username()
    if username:
        correct = input("Are you " + username + "? (y/n) ")
        if correct == 'y':
            print("Welcome back, " + username + "!")
            return

    # 获得了用户名,但不对。
    # 因此提示用户输入其用户名。
    username = get_new_username()
    print("We'll remember you when you come back, " + username + "!")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值