python——文件和异常

  • 文件,让程序能够快速分析大量数据。
  • 异常是python创建的特殊对象,用于管理程序运行时出现的错误。
  • 模块json,让你能够保存用户数据,以免在程序停止运行后丢失。

从文件中读取数据

1.读取整个文件
  • python在当前执行文件所在的目录中查找指定的文件。
  • 关键字With在不再需要文件后将其关闭。你只管打开文件,并在需要时使用它,python会在合适的时候自动将其关闭。
  • read()方法读取这个文件的全部内容。
with open('pi_digits.txt') as file_object:
    contents=file_object.read()
    print(contents)    

函数open()接受一个参数,要打开的文件的名称。
open('pi_digits.txt')返回一个表示文件pi_digits.txt的对象,python将这个对象存储在我们将在后面使用的变量中。
print(contents.rstrip) read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行,要删除末尾的空行,可以在print语句中使用rstrip().

2.文件路径
  • with open('text_files\filename.txt') as file_object:让python到文件夹text_files中去查找指定的.txt文件。
  • 绝对文件路径,文件在计算机中的准确位置,绝对路径通常比相对路径长,因此将其存储在一个变量中,再将该变量传递给open()会有所帮助。
  • 在Windows中为确保万无一失,应以原始字符串的方式指定路径,即在开头的单引号前加r。
3.逐行读取
  • 要以每次一行的方式检查文件,可对文件对象使用for循环
filename='pi_digits.txt'
with open(filename) as file_object:
    for line in file_object:
        print(line.rstrip())

11111
222222
333333

文件每行末尾会有一个看不见的换行符,而且print也会加上一个换行符,为消除这些多余的空白行,可在print语句使用rstrip()

4.创建一个包含文件各行内容的列表
  • 使用关键字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())

readlines()从文件中读取每一行,并将其存储在一个列表中,接下来,该列表被存储到变量lines中,在with代码块外,我们依然可以使用这个变量。

5.使用文件的内容
  • 将文件读取到内存后,就可以以任何方式使用这些数据了。
  • 读取文件时,python将其中的所有文本都解读为字符串
filename='pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()

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

print(pi_string)
print(len(pi_string))

打开文件,将其中的所有行都存储到一个列表中,变量pi_string用于存储文件中的内容,使用一个循环将各行都加入到pi_string,并使用rstrip()删除每行末尾的换行符,然后再打印这个列表以及列表的长度。

10-2 C语言学习笔记
filename='pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
    for line in lines:
        print(line.rstrip().replace('python','c'))

写入文件

1.写入空文件
  • 要将文本写入文件,在调用open()时需要提供一个实参,告诉python你要写入打开的文件。
  • 写入'w'模式打开文件时,如果指定的文件已经存在,python将在返回对象前清空该文件。
finename='pi_digits.txt'
with open(finename,'w') as file_object:
    file_object.write('wenwen')

调用open()提供两个实参,第一个实参是要打开的文件名称,第二个实参w告诉python我们要以写入模式打开这个文件。打开文件时,可以指定读取模式‘r',写入模式'w',附加模式'a',能够读取和写入文件的模式'r+',如果省略模式实参,python以默认的只读模式打开文件。

2.写入多行
  • 要让每个字符串都单独占一行,需要在write()语句中包含换行符。
finename='pi_digits.txt'
with open(finename,'w') as file_object:
    file_object.write('I love my life.\n')
    file_object.write('I love my lover.\n')

附加到文件

  • 如果要添加文件,而不是覆盖原有的内容,可以附加模式打开文件,以这种模式打开文件时,python不会在返回文件对象前清空文件,而你写入到文件的行都将添加到文件末尾,如果指定的文件不存在,python将会为你创建一个空文件。
finename='pi_digits.txt'
with open(finename,'a') as file_object:
    file_object.write('I fell happy now.\n')
    file_object.write('I love my boyfriend.')

打开文件时指定实参a,以便将内容附加到文件末尾,而不是覆盖文件原来的内容。

10-4访客名单
filename = 'guest.txt'
while True:
    name = input("请输入你的名字:")
    if name =='q':
        break

    with open(filename,'a') as file_object:
        file_object.write(name)
        file_object.write('\n')

异常

1.处理ZeroDivisionError
  • 将一个数字除以0,就会引发这个错误。
  • 在这种错误中,ZeroDivisionError是一个异常对象,在这种情况下,python停止运行程序,指出发生哪种异常,我们可根据提示对程序进行修改。
2.使用try-except代码块
  • 认为可能发生了错误时,使用try-except代码块来处理可能引发的异常。
try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero.")

如果try代码块中的代码运行起来没有问题,python将跳过except代码块;如果try代码块中的代码导致了错误,python将查找这样的except代码块,并运行其中的代码,即指定的错误与引发的错误相同。

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("\nSecond 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 "D:/python/untitled/ten/division.py", line 18, in <module>
    answer = int(first_number)/int(second_number)
ZeroDivisionError: division by zero
4.else代码块
  • 通过将可能引发错误的代码放在try-except代码块中,可提高这个程序抵御错误的能力。
  • 依赖于try代码块成功执行的代码块都应放到else代码块中。
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("\nSecond number:")
    
    try:
        answer = int(first_number)/int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0!")
    else:
        print(answer)

try-except-else代码块的工作原理

  • python尝试执行try代码块中的代码。
  • 只有可能引发异常的代码才需要放在try语句中
  • 有一些仅在try代码块成功执行时才需要运行的代码,这些代码要放在else代码块中。
  • except代码块告诉python,如果它尝试运行try代码块中的代码时引发了指定的异常,该怎么办。
5.处理FileNotFoundError异常
  • 找不到文件时,可以使用try-except代码块以直观的方式进行处理。

尝试读取一个不存在的文件

filename='alice.txt'
with open(filename) as f_obj:
    contents=f_obj.read()

Traceback (most recent call last):
  File "D:/python/untitled/ten/division.py", line 26, in <module>
    with open(filename) as f_obj:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'

将其放在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)
else:
    # 计算文件大致包含多少个单词
    words=contents.split()
    num_words=len(words)
    print("The file "+filename+" has about "+str(num_words) + " words.")

对变量contents调用方法split(),以生成一个列表,其中包含这个文件中的所有单词,使用len()来确定这个列表的长度。

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','pi_digits.txt','guest.txt','abc.txt']
for filename in filenames:
    count_words(filename)

The file alice.txt has about 6 words.
The file pi_digits.txt has about 16 words.
The file guest.txt has about 3 words.
Sorry,the file abc.txt does not exist.
8.失败时一声不吭
  • python有一个pass语句,可在代码块中使用它来让python什么都不做。
def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        pass

    else:
        # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) + " words.")

filenames = ['alice.txt','pi_digits.txt','guest.txt','abc.txt','lla.txt']
for filename in filenames:
    count_words(filename)

The file alice.txt has about 6 words.
The file pi_digits.txt has about 16 words.
The file guest.txt has about 3 words.

出现FileNotFoundError异常时,将执行except代码块中的代码,但什么都不会发生,这种错误发生时,不会出现traceback,也没有任何输出。用户将看到存在的每个文件包含多少个单词,但是没有任何迹象表明有一个文件未找到。

存储数据

  • 使用json模块来存储数据
  • 模块json能够将简单的python数据结构存储到文件中,并在程序再次运行时加载该文件中的数据。
1.使用json.dump()和json.load()
  • 存储一组数字的简短程序使用函数json.dump()接受两个实参:要存储的数据以及可用于存储数据的文件对象。
  • 将存储的数字读取到内存中,使用函数json.load(),这是一种在程序之间共享数据的简单方式。

使用json.dump()来存储数字列表

import json

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

filename='number.json'
with open(filename,'w') as f_obj:
    json.dump(numbers,f_obj)

通常使用文件扩展名.json来指出文件存储的数据为JSON格式。

使用json.load()将这个列表读取到内存中

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

print(numbers)

filename='number.json'是为了确保读取的是前面写入的文件。以读取方式打开这个文件,使用函数json.load()加载存储在number.json中的信息,并将其存储到变量numbers中。

2.保存和读取用户生成的数据
  • 对于用户生成的数据,如果不以某种方式进行存储,等程序停止运行时,用户的信息将丢失。
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 +"!")

用户首次运行这个程序时,文件username.json不存在,将引发FileNotFoundError异常,因此python将执行except代码块。提示用户输入用户名,再使用json.dump()存储该用户名,并打印一句问候语。

3.重构
  • 重构: 代码可以正确运行,但可以做进一步改进,将代码划分为一系列完成具体工作的函数。
  • 如果想要重构remem_me.py,可将其大部分逻辑放到一个或多个函数中。
import json
def get_sorted_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_sorted_username()
    if username:
        print("welcome back, " + username +"!")
    else:
        username = get_new_username()
        print("We'll remember you when you come back, " + username +"!")

greet_user()

使用重构,让每个函数都执行单一而清晰的任务。

10-13 验证用户
import json
def get_sorted_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_sorted_username()
    if username:
        your_name=input("Is the name:"+username+", True/False")
        if your_name=='True':
            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()
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值