python -- 中

九、文件和异常

1、从文件中读取数据

  要使用文本文件中的信息,首先需要将信息读取到内存中,可以一次性读取文件的全部内容,也可以每次一行的方式逐步读取。

  ①读取整个文件

#在当前目录下创建一个文本为 Nine-test.txt,然后使用代码读取这个文本
  
with open('Nine-test') as file_object:
contents = file_object.read()
print(contents)

  

  函数 open() :要以任何方式使用文件,哪怕是仅仅打印其内容,都要先打开文件才能访问它,函数 open() 接受一个参数,为要打开文件的名称,Python 在当前执行的文件所在的目录中查找指定的文件,函数 open() 返回一个表示文件的对象,返回的是文本,Python 将这个对象存储在我们将在后面使用的变量中。

  关键字 with 在不需要访问文件后将其关闭。

  read() 到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行,要删除多余的空行,可在 print 语句中使用 rstrip()

  ②文件路径

  要让Python打开不与程序文件位于同一个目录中的文件,需要提供文件路径。

#在 Linux 和 OS X 系统中:( / )
with open('text_files/filename.txt') as file_object:
#在windows 系统中:( \ )
with open('text_files\filename.txt') as file_object:

  可将计算机中准确的位置告诉Python,这称为绝对路径:

file_path = 'C:/Users/rx801/PycharmProjects/study/Nine_test.txt'
with open(file_path) as file_object:
    content = file_object.read()
    print(content)

  ③逐行读取

  读取文件时,常常需要检查其中的每一行,可能需要在文件中查找特定的信息,或者要以某种方式修改文件中的文本

  例如:遍历一个包含天气的文件,并使用天气描述中包含字样 sunny 的行,或在新闻报道中查找包含标签<headline>的行。

  要以每次一行的方式检查文件,可对文件对象使用 for 循环。

file_path = 'Nine-test'            #将要读取的文件名称存储在变量 filename 中,这是使用文件时一种常见的做法
with open(file_path) as file_object:  #调用 open() 后,将一个表示文件及其内容的对象存储到了变量 file_object 中。
    for line in file_object:
        print(line.rstrip())        #使用 rstrip 消除每次输出后面的换行符。否则每行末尾都有两个换行符,一个来自文件,另一个来自print语句

 

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

  使用关键字 with 时,open() 返回的文件对象只在 with 代码块内可用,如果要在 with 代码块外访问文件的内容,可在 with代码块内将文件的各行存储在一个列表中,并在 with 代码块外使用该列表;你可以立即处理文件的各个部分,也可推迟到程序后面再处理。

file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path) as file_object:
    line = file_object.readlines()

for item in line:
    print(item.rstrip())

 

  readlines() 方法从文件中读取每一行,并将其存储在一个列表中,该列表存储在变量 line 中。

  ⑤使用文件的内容

   将文件读取到内存中后,就可以以任何方式使用这些数据了

#圆周率值,创建一个字符串,包含文件中的所有数字,且没有任何空格
file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path) as file_object:
    line = file_object.readlines()
pi_string = ''
for item in line:
    pi_string += item.strip()  #拼接字符串
print(pi_string)
print(len(pi_string))

 

#读取一百万位的文件,显示前50位,示例
file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path) as file_object:
    line = file_object.readlines()
pi_string = ''
for item in line:
    pi_string += item.strip()
print(pi_string[:52] + "...")

 

  对于可处理的数据量,Python 没有任何限制;只要系统的内存足够多,想处理多少数据都可以。

#检查生日是否包含在圆周率中
file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path) as file_object:
    line = file_object.readlines()
pi_string = ''
for item in line:
    pi_string += item.strip()
birthday = input("Please input your Birthday: ")
if birthday in pi_string:
    print("Yes,exist!")
else:
    print("No,Not Exist!")

 

2、替换文件内容 -- replace()

  方法 replace() 将字符串中的特定单词替换为另一个单词。

message = "I Like Python"
message.replace('Python','Linux')  #只是临时修改,永久修改需要将修改后的重新定义到变量中,message = message.replace('Python','Linux')

 

 

 3、写入文件

  保存数据最简单的方式之一是将其写入到文件中,通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出依然存在,可以在程序结束运行后查看这些输出,可与别人分享输出文件,还可编写程序来将这些输出读取到内存中并进行处理。

  ①写入空文件

  要将文本写入文件,在调用 open() 时需要提供另一个实参,告诉Python要写入打开的文件

file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path,'w') as file_object:
    file_object.write("I Like Shell")
with open(file_path) as file_a:
    print(file_a.read())

 

  在这个示例中,Python 调用了两个实参,第一个实参是要打开的文件的名称,第二个实参(‘w’)告诉Python要以写入模式打开这个文件,打开文件时,可指定读取模式(’r‘),写入模式('w'),附加模式('a'),能够读取和写入文件的模式('r+'),如果省略了默认实参,Python将以默认只读的模式打开文件。

  如果写入的文件不存在,函数open() 会创建它,使用('w')模式打开文件时,如果指定的文件已经存在,Python 将在返回文件对象前清空该文件。

  使用文件对象的方法 write() 将一个字符串写入文件。

  ※Python只能将字符串写入文本文件,要将数值数据存储到文本文件中,必须使用函数 str() 将其转换为字符串格式。

  ②写入多行

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

file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path,'r+') as file_object:
    file_object.write("I Like Python.")
    file_object.write("I Like Linux.")

 

#加入换行符
file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path,'r+') as file_object:
    file_object.write("I Like Python.\n")
    file_object.write("I Like Linux.\n")

 

  ③附加文件(追加文件)

  要给文件添加内容,而不是覆盖原有的内容,以附加模式打开文件,写入到文件的行都将添加到文件末尾,如果指定的文件不存在,Python将创建一个空文件。

file_path = 'C:/Users/rx801/new_test.txt'
with open(file_path,'a') as file_object:
    file_object.write("I Like Python.\n")
    file_object.write("Python is very good!")

 

#编写一个while 循环,提示用户输入其名字。用户输入其名字后,在屏幕上打印一句问候语,并将一条访问记录添加到文件guest.txt中。确保这 个文件中的每条记录都独占一行
file_path = 'C:/Users/rx801/guest.txt'
while True:
    name = input("Please input your name: ")
    if name == 'quit':
        break
    else:
        message = "Hello,"+name+".\n"
        print(message)
        with open(file_path,'a') as file_name:
            file_name.write(message)

 

 

4、异常

  Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果编写了处理该异常的代码,程序将继续执行,如果未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。

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

  ①处理 ZeroDivisionError 异常

print(5/0)

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-6-fad870a50e27> in <module>
----> 1 print(5/0)

ZeroDivisionError: division by zero

  Python 无法按照你的要求做时,就会创建这种对象,Python 将停止运行程序,并指出引发了哪种异常。

  ②使用 try-except 代码块

  当你认为可能发生错误时,可编写一个 try-except 代码块来处理可能引发的异常。

#处理 ZeroDivisionError 异常的 try-except 代码块类似这样:
try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")

 

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

  如果 try-except 后面还有其他代码,程序将接着运行。

  ③else 代码块

while True:
    first_number = input("Please input first number: ")
    if first_number == 'quit':
        break
    second_number = input("Please input second number: ")
    if second_number == 'quit':
        break
    try:
        answer = int(first_number) / int(second_number)
    except:
        print("Error,Please input right number !")
    else:
        print(answer)

 

  ※ try-except-else 代码块的工作原理:Python 尝试执行 try 代码块中的代码,只有可能引发异常的代码才需要放在 try 语句中,仅在 try 代码块成功执行时才需要运行的代码放在 else 代码块中,except 代码块告诉 Python,尝试运行 try 代码块中的代码时引发了指定的异常怎么处理。

  ④处理 FileNotFoundError 异常

  使用文件时,一种常见的问题是找不到文件,要查找的文件可能在其他地方、文件名可能不正确或者这个文件根本不存在。

file_path = 'C:/Users/rx801/Error.txt'
with open(file_path) as file:
    print(file.read())
  
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-14-a6e913997e4e> in <module>
      1 file_path = 'C:/Users/rx801/Error.txt'
----> 2 with open(file_path) as file:
      3     file.read()

FileNotFoundError: [Errno 2] No such file or directory: 'C:/Users/rx801/Error.txt'

  使用 try-except 代码块

file_path = 'C:/Users/rx801/Error.txt'
try:
    with open(file_path) as file:
        content = file.read()
except:
    print("Not Find This File!")
else:
    print(content)

 

  ⑤分析文本

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

title = 'C:/Users/rx801/new_test.txt'

try:
    with open(title) as file:
        contents = file.read()
except:
    print("file does not exist!")
else:
    #计算文件包含多少单词 words
= contents.split() num_words = len(words) print("The title has "+str(num_words)+" words!")

 

  使用 for 循环查看多个文件

def count_words(title):
    try:
        with open(title) as file:
            contents = file.read()
    except:
        print("file does not exist!")
    else:
        words = contents.split()
        num_words = len(words)
        print("The title has "+str(num_words)+" words!")
title = ['C:/Users/rx801/guest.txt','C:/Users/rx801/new_test.txt','C:/Users/rx801/abcd.txt']
for item in title:
    count_words(item)

 

  ⑥失败时一声不吭

  在前一个示例中,有一个文件找不到,但并不是每次有异常都需要告诉用户,希望程序在发生异常时一声不吭继续运行,只需在except代码块告诉Python什么都不要做。

  使用 pass 语句可让发生异常时什么都不做。

def count_words(title):
    try:
        with open(title) as file:
            contents = file.read()
    except:
        pass
    else:
        words = contents.split()
        num_words = len(words)
        print("The title has "+str(num_words)+" words!")
title = ['C:/Users/rx801/guest.txt','C:/Users/rx801/new_test.txt','C:/Users/rx801/abcd.txt']
for item in title:
    count_words(item)

 

  count() 方法可以确定特定的单词或短语在字符串中出现了多少次。

pets = "dog,cat,fish,Cat,pig,CAT"
pets.lower().count('cat')

 

  使用 lower() 将字符串变为小写,再查找相应的字符串。

5、存储数据

  模块 json 能够将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件的数据,还可以使用 json 在 Python 程序之间分享数据。

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

  函数 json.dump() 接受两个实参:要存储的数据以及可用于存储数据的文件对象。

import json
numbers = [2,3,4,5,6,7]
filename = 'C:/Users/rx801/numbers.txt'
with open(filename,'w') as f_obj:
    json.dump(numbers,f_obj)

 

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

import json
filename = 'C:/Users/rx801/numbers.txt'
with open(filename) as f_obj:
    numbers = json.load(f_obj)
print(numbers)

 

  读取前面写入的文件,使用函数 json.load() 加载存储在 numbers.json 中的信息,并将其存储到变量 numbers 中,最后打印数字列表。

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

  对于用户生成的数据,如果不以某种方式进行存储,等程序停止运行时用户的信息将丢失。

#保存用户生成的数据
import json
filename = 'C:/Users/rx801/numbers.txt'
username = input("What's your name? ")
with open(filename,'w') as file_object:
    json.dump(username,file_object)

#读取用户保存的数据
import json
filename = 'C:/Users/rx801/numbers.txt'
try:
    with open(filename) as file_object:
        username = json.load(file_object)
except FileNotFoundError:
    username = input("What's your name? ")
    with open(filename,'w') as f_obj:
        json.dump(filename,f_obj)
        print("welcome back: "+username)
else:
    print(username)

 十、测试代码

  编写函数或类时,可为其编写测试。通过测试,可确定代码面对各种输入都能够按要求的那样工作,在程序中添加新代码时,也可以对其进行测试,确认它们不会破坏程序既有的行为,经常测试代码,在用户发现问题前找出它们。

1、单元测试和测试用例

  Python标准库中的模块 unittest 提供了代码测试工具。

  单元测试用于核实函数的某个方面有没有问题。

  测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。良好的测试用例考虑到了函数可能接收到的各种输入。

  全覆盖式测试:用例包含一整套单元测试,涵盖了各种可能的函数使用方式。

#main_user.py
def greet_user(first_name,last_name):
    full_name = first_name+' '+last_name
    return full_name

#Users.py
import unittest
from  main_user import greet_user
class NameTestCase(unittest.TestCase):    #创建的类名随便起,但是最好和测试相关并包含Test,这个类必须继承unittest.TestCase类,这样Python才知道如何运行测试。
    '''测试 main_user.py'''
    def test(self):
        full_name = greet_user('Steven','Curry')
        '''使用unittest类的断言方法'''
        self.assertEqual(full_name,'Steven Curry')  #如果full_name的值与字符串'Steven Curry'相等,就OK,不相等就Fail
unittest.main()

  assertEqual 方法是 unittest 类最有用的功能之一:一个断言方法,断言方法用来核实得到的结果是否与期望的结果一致。

 

2、测试类

  ①各种断言方法

  Python 在unittest.TestCase类中提供了很多断言方法。断言方法检查你认为应该满足的条件是否确实满足。

  ②unittest Module中的断言方法:

posted @ 2021-03-11 10:31  Lillard-Time  阅读(159)  评论(0编辑  收藏  举报