文件和异常(从文件中读取数据、写入文件、异常、存储文件)

目录

从文件中读取数据

        读取整个文件

        文件路径

        逐行读取

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

        使用文件的内容

        包含一百万位的大型文件

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

写入文件

        写入空文件

        写入多行

        附加到文件

异常

        处理 ZeroDivisionError 异常,使用 try-except 代码块

        try-except-else代码块

        处理 FileNotFoundError 异常,使用 try-except 代码块

        分析文本

        使用多个文件

        失败时一声不吭

        决定报告哪些错误

存储文件

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

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

        重构


从文件中读取数据

#——————————————————————文件和异常——————————————————————————


#————————从文件中读取数据——————————
 #创建一个文件digits.txt存储数据。新一个.py文件来打开该文件
'''文件内容:
        3.1415926535 
          8979323846 
          2643383279 '''

with open('digits.txt') as f:
    contents = f.read()
    print(contents.rstrip())    #方法rstrip()删除(剥除)字符串末尾的空白
    
#————————文件路径—————————————————

#绝对路径:一般起始于某个盘,结束于该文件实际位置
path_1 = 'F:\python练习\python\A基础语法\digits.txt'
#相对路径:是指相对于当前文件所在的路径,一般比较简短
path_2 ='python\A基础语法\digits.txt'  
#若与当前目录在同一文件夹下
path_3 = 'digits.txt'

'''注意 Windows系统有时能够正确地解读文件路径中的斜杠。如果你使用的是Windows系统,且
结果不符合预期,请确保在文件路径中使用的是反斜杠。'''

filename = 'digits.txt' 

#——————逐行读取———————————————————————
with open(filename) as f:
    for line in f:
        print(line.rstrip())

#————创建一个包含文件各行内容的列表————
with open(filename) as f:
    lines = f.readlines()
    print(lines)      #验证打印列表
    #方法readlines()从文件中读取每一行,并将其存储在一个列表中
    for line in lines:
        print(line)

#——————使用文件的内容——————————————————
with open(filename) as f:
    lines = f.readlines()
#变量string,用于存储圆周率的值
string= ''
for line in lines:
    #string存储的字符串中,包含原来位于每行左边的空格,
    #为删除这些空格,可使用strip()而不是rstrip()
    string  += line.strip()   
print(string)
print(len(string))

#——————包含一百万位的大型文件————————————
filename_2 = 'pi_million_digits.txt'

with open(filename_2) as f:
    lines = f.readlines()
string = ''
for line in lines:
    string += line.strip()
print(string[:53]+'...')
print(len(string))

#—————圆周率值中包含你的生日吗——————————

with open(filename_2) as f:
    lines = f.readlines()
string = ''
for line in lines:
    string += line.rstrip()
birthday = input('请输入你的生日:')
if birthday in string:
    print('你的生日在Π小数点后百万位中。')
else:
    print('你的生日不在Π小数点后百万位中。')

写入文件

##——————————————————————————写入文件——————————————————————————————————————————

'''。打开文件时,可指定读取模式('r')、写入模式('w')、
附加模式('a')或让你能够读取和写入文件的模式('r+')。
如果你省略了模式实参,Python将以默认的只读模式打开文件。
如果你要写入的文件不存在,函数open()将自动创建它。然而,以写入('w')模式打开文
件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件。'''

#———————— 写入空文件——————————
filename_3 = 'programing.txt'

with open (filename_3, 'w') as f:
    f.write('I love python!')

#————————写入多行——————————————

#函数write()不会在你写入的文本末尾添加换行符,因此如果你写入多行时需指定换行符

异常

'''异常是使用try-except代码块处理的。try-except代码块让Python执行指定的操作,同时告
诉Python发生异常时怎么办。使用了try-except代码块时,即便出现异常,程序也将继续运行:
显示你编写的友好的错误消息,而不是令用户迷惑的traceback'''

# ————————处理 ZeroDivisionError 异常————
'''的错误ZeroDivisionError是一个异常对象。Python无法按你的
要求做时,就会创建这种对象。在这种情况下,Python将停止运行程序,并指出引发了哪种异常,
而我们可根据这些信息对程序进行修改。'''

#——————使用 try-except 代码块————————————
try: 
    print(5/0) 
except ZeroDivisionError: 
    print("You can't divide by zero!") 

#——————使用异常避免崩溃——————————————————
#try-except-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("Second 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代码块中
的代码时引发了指定的异常,该怎么办。
通过预测可能发生错误的代码,可编写健壮的程序,它们即便面临无效数据或缺少资源,也
能继续运行,从而能够抵御无意的用户错误和恶意的攻击。'''

#———————— 处理 FileNotFoundError 异常———————

'''使用文件时,一种常见的问题是找不到文件:你要查找的文件可能在其他地方、文件名可能
不正确或者这个文件根本就不存在。对于所有这些情形,都可使用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) 

#try代码块引发FileNotFoundError异常,因此Python找出与该错误匹配的
#except代码块,并运行其中的代码。最终的结果是显示一条友好的错误消息,而不是traceback:

#————————分析文本————————————————
filename = 'digits.txt'

try: 
    with open(filename) as f: 
        contents = f.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.')
    
#——————使用多个文件————————————————
def count_words(filename):
    
    try: 
        with open(filename) as f: 
            contents = f.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代码块提供了两个重要的优点:避免让用户看到traceback;
#让程序能够继续分析能够找到的其他文件。

#————————失败时一声不吭————————————
def count_words(filename):
    
    try: 
        with open(filename) as f: 
            contents = f.read() 
    except FileNotFoundError: 
        pass            #pass语句,可在代码块中使用它来让Python什么都不要做
    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)
    
#pass语句还充当了占位符,它提醒你在程序的某个地方什么都没有做,
# 并且以后也许要在这里做些什么。

#————————决定报告哪些错误————————————————
'''
    在什么情况下该向用户报告错误?在什么情况下又应该在失败时一声不吭呢?如果用户知
道要分析哪些文件,他们可能希望在有文件没有分析时出现一条消息,将其中的原因告诉他们。
如果用户只想看到结果,而并不知道要分析哪些文件,可能就无需在有些文件不存在时告知他们。
向用户显示他不想看到的信息可能会降低程序的可用性。Python的错误处理结构让你能够细致地
控制与用户分享错误信息的程度,要分享多少信息由你决定。
    编写得很好且经过详尽测试的代码不容易出现内部错误,如语法或逻辑错误,但只要程序依
赖于外部因素,如用户输入、存在指定的文件、有网络链接,就有可能出现异常。凭借经验可判
断该在程序的什么地方包含异常处理块,以及出现错误时该向用户提供多少相关的信息。'''

存储文件

#————————————————————————存储数据————————————————————————————————————————————————————


#——————使用 json.dump()和 json.load()——————
import json

#使用函数json.dump()将数字列表存储到文件numbers.json中
numbers = [2,4,5,7,10]
filename = 'numbers.json'
with open (filename,'w') as f:
    #函数json.dump()接受两个实参:要存储的数据以及可用于存储数据的文件对象
    json.dump(numbers,f)
    
#使用函数json.load()加载存储在numbers.json中的信息
filename = 'numbers.json'
with open (filename) as f:
    numbers = json.load(f)
print(numbers)

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

import json

filename = 'username.json'
try:
    # 如果以前存储了用户名,就加载它
    with open (filename) as f:
        username = json.load(f)
#否则,就提示用户输入用户名并存储它        
except FileNotFoundError:
    username = input('What is your name?')
    filename = 'username.json'
    with open (filename,'w') as f:
        json.dump(username,f)
        print('We will remeber you when you come back,' + username.title() + '!')

else:
    print("Welcome back, " + username + "!")

#————————————重构————————————————————————

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

import json

def get_old_username():
#若存储了用户名就获取它
    filename = 'username.json'
    try:
        with open(filename)as f:
            username = json.load(f)
    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:
        json.dump(username,f)
    return username
def greet_user():
#问候用户,并指出名字
    username = get_old_username()
    if username:
        print('Welcome,'+username+ '!')
    else:
        username = get_new_username()
        print('We will remeber you when you come back,' + username.title() + '!')
greet_user()

'''每个函数都执行单一而清晰的任务。我们调用greet_user(),它打印一条合适的消息:
要么欢迎老用户回来,要么问候新用户。为此,它首先调用get_stored_username(),
这个函数只负责获取存储的用户名(如果存储了的话),再在必要时调用get_new_username(),
这个函数只负责获取并存储新用户的用户名。要编写出清晰而易于维护和扩展的代码,
这种划分工作必不可少。'''

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值