使用文本文件的信息,需要将信息读取到内存中。
读取整个文件
创建文件pi_digits.txt
file_reader.py
with open('pi_digits.txt') as file_object:
contents=files_object.read()
print(contents)
关键字with在不需要访问文件后将其关闭,read()到达文件末尾会返回一个空字符串,空字符串输出就是一个空行。
删除末尾的空行,可以在print语句中使用rstrip()
print(contents.rstrip())
文件路径:在windows系统中,文件路径使用反斜杠
with open(‘text_file\filename.txt’) as file_object:
将文件在计算机中的准确位置告诉python,不用关心当前运行的程序存储在哪,此时文件路径为绝对路径。
file_path='C:\Users\other_files\text_files\filename.txt'
with open(file_path) as file_object:
通过使用绝对路径,可以读取系统任何地方的文件。
逐行读取
filename='pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())#消除每一行之后的空行
创建一个包含文件各行内容的列表
filename='pi_digits.txt'
with open(filename) as file_object:
lines=file_object.readlines() #从文件中读取每一行,并将其存储在一个列表中
for line in lines:
print(line.rstrip())
使用文件的内容
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))
删除每行左边的空格可以使用strip()
pi_string+=line.strip()
读取文本文件时,python将其中的所有文本都解读为字符串,如果读取的是数字,并将其作为数值使用,需要使用函数int()转换为整数,或使用float()转换为浮点数。
包含一百万位的大型文件
for line in lines:
pi_string+=line.strip()
print(pi_string[:52]+"…") #只打印小数点后50位
print(len(pi_string)) #打印字符串的长度
写入文件
将文本写入空文件
filename='programming.txt'
with open(filename,'w') as file_object:
file_object.write("I love programming.")
写入多行
with open(filename,'w') as file_object:
file_object.write("I love programming.")
file_object.write("I love create new games")
函数write()不会再写入的文本末尾加换行符,如果写入多行需要自行制定换行符
with open(filename,'w') as file_object:
file_object.write("I love programming.\n")
file_object.write("I love create new games.\n")
附加到文件
如果要给文件添加内容,不是覆盖原有的内容,使用附加模式打开文件,写入到文件的行都将添加到文件末尾。
如果指定的文件不存在,python会创建一个空文件。
filename='programming.txt'
with open(filename,'a') as file_object:
file_object.write("aaaaa.\n")
file_object.write("bbbbb.\n")
异常
python使用被称为异常的对象来管理程序执行期间发生的错误,每当执行到错误,都会创建一个异常对象。
如果编写了处理该异常的代码,程序将会继续执行,如果未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的警告。
异常是使用try-except代码块处理的。
处理ZeroDivisionError异常
try:
print(5/0)
except ZeroDivisionError:
print("You can’t divide by zero!")
使用异常避免崩溃
如果程序能够妥善处理无效输入,就能再提示用户提供有效输入,不至于崩溃。
print("Give me two numbers, and I’ll divide them.")
print("Enter 'q' to quit.")
while True:
first_number=input("input first number:")
if first_number=='q':
break
second_number=input("second_number:")
if second_number=='q':
break
answer=int(first_number)/int(second_number)
print(answer)
将可能引发错误的代码放在try-except代码块中,可以提高这个程序抵御错误的能力。
while True:
first_number=input("input first 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: #依赖于try代码块成功执行的代码放到else代码块中
print(answer)
处理FileNotFoundError异常
找不到文件
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)
分析文本
分析文本中包含多少个单词,使用方法split(),根据字符串创建一个单词列表
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.")
使用多个文件
先将程序的大部分代码移到一个函数中。
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.")
filename='alice.txt'
count_words(filename)
filenames=['alice.txt','moby_dick.txt','little_women.txt']
for filename in filenames:
count_words(filename)
并非捕获到异常都需要告诉用户,有时候希望程序发生异常后一声不吭。
try:
…
except FileNotFoundError:
pass #不处理错误
else:
…
存储数据
很多程序都要求用户输入某种信息,程序会把用户提供的信息存储在列表和字典等数据结构中,用户关闭程序时,几乎总是要保存他们提供的信息,一种简单的方式是使用模块json存储数据。
模块json可以将简单的python数据结构存储到文件中,并在程序再次运行时加载文件中的数据,还可以用json在python程序之间分享数据。
可以以JSON格式存储的数据与使用其他编程语言的人分析。
使用json.dump()和json.load()
json.dump()接受两个实参:要存储的数据和可用于存储数据的文件对象。
import json
numbers=[2,3,4,6,8]
filename='numbers.json'
with open(filename,'w') as f_obj:
json.dump(numbers,f_obj)
使用json.load()将这个列表读取到内存中
import json
filename='numbers.json'
with open(filename) as f_obj:
numbers=json.load(filename)
print(numbers)
保存和读取用户生成的数据
使用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("welcome back, "+username+"!")
将两个程序合并到一起
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+"!")
重构
当代码能够运行,但是可以进一步改进,将代码划分为一系列完成具体工作的函数,称为重构。
重构可以让代码更清晰、更易于理解、更容易扩展。
重构remember.py
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()
重构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:
username= nput(“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+"!")
greet_user()
测试代码
编写函数或类时,还可以编写测试,通过测试,可以确定代码面对各种输入都能够按照要求那样工作。
使用python模块unittest中的工具测试代码,编写测试用例,核实一系列输入都将得到预期输出。
单元测试和测试用例
python标准库中的模块unittest提供了代码测试工具,单元测试用于核实函数的某个方面没有问题;
测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。
良好的测试用例考虑到函数可能收到的各种输入,包含针对所有这些情形的测试。
全覆盖式测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。
最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。
可通过的测试
测试函数name_function.py
def get_formatted_name(first,last):
full_name=first+' '+last
return full_name.title()
测试用例test_name_function.py
import unittest #导入模块
from name_function import get_formatted_name #导入测试函数
class NamesTestCase(unittest.TestCase): #创建一个继承unittest.TestCase的类
def test_first_last_name(self):
formatted_name=get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')#断言方法核实得到的结果是否与期望的结果一致
unittest.main()#让python运行这个文件中的测试
不能通过的测试
name_function.py
def get_formatted_name(first,middle,last):
full_name=first+' '+middle+' '+last
return full_name.title()
测试用例NamesTestCase 的函数test_first_last_name未通过
修改:将形参middle移到形参列表末尾
def get_formatted_name(first, last,middle=''):
添加新测试
import unittest #导入模块
from name_function import get_formatted_name #导入测试函数
class NamesTestCase(unittest.TestCase): #创建一个继承unittest.TestCase的类
def test_first_last_name(self):
formatted_name=get_formatted_name('janis','joplin')
self.assertEqual(formatted_name,'Janis Joplin')#断言方法核实得到的结果是否与期望的结果一致
def test_first_middle_last_name(self):
formatted_name=get_formatted_name('wolfgang','mozart','amadeus')
self.assertEqual(formatted_name,'Wolfgang Mozart Amadeus')
unittest.main()#让python运行这个文件中的测试
测试类
编写针对类的测试
python的unittest.TestCase类提供的各种断言方法:
一个要测试的类
survey.py
class AnoymousSurvey():
def __init__(self,question):
self.question=question
self.responses=[]
def show_question(self):
print(self.question)
def store_response(self,new_response):
self.responses.append(new_response)
def show_results(self):
print("Suvery results:")
for response in self.responses:
print('-'+response)
为了证明AnoymousSurvey类能正确工作,编写一个使用它的程序
language_survey.py
from survey import AnoymousSurvey
question="What language did you first learn to speak?"
my_survey=AnoymousSurvey(question)
my_survey.show_question()
print("Enter 'q' at any time to quit.\n")
while True:
response=input("Language:")
if(response=='q'):
break
my_survey.store_response(response)
print("\nThank you to everyone who participated in the survey!")
my_survey.show_results()
测试AnoymousSurvey类
test_survey.py
import unittest
from survey import AnoymousSurvey
class TestAnoymousSurvey(unittest.TestCase):
def test_stored_single_response(self):
"""测试单个答案"""
question=”What language did you first learn to speak?"
my_survey=AnoymousSurvey(question)
my_survey.store_response('English')
self.assertIn('English',my_survey.responses)
def test_stored_three_responses(self):
"""测试三个答案"""
question="What language did you first learn to speak?"
my_survey=AnoymousSurvey(question)
responses=['English','Spanish','Mandarin']
for response in responses:
my_survey.store_response(response)
for response in responses:
self.assertIn(response,my_survey.responses)
unittest.main()
unittest.TestCase类包含方法setUp(),只需创建这些对象一次,并在每个测试方法中使用他们。
如果TestCase类中包含方法setUp(),python将先运行它,再运行各个以test_开头的方法。
这样在每个测试方法中都可以使用方法setUp()中创建的对象了。
import unittest
from survey import AnoymousSurvey
class TestAnoymousSurvey(unittest.TestCase):
def setUp(self):
question="What language did you first learn to speak?"
self.my_survey= AnoymousSurvey(question)
self.responses=['English','Spanish','Mandarin']
def test_stored_single_response(self):
"""测试单个答案"""
self.my_survey.store_response('English')
self.assertIn(self.responses[0],self.my_survey.responses)
def test_stored_three_responses(self):
"""测试三个答案"""
for response in self.responses:
self.my_survey.store_response(response)
for response in self.responses:
self.assertIn(response,my_survey.responses)
unittest.main()
测试自己编写的类时,方法setUp()让测试方法编写起来更容易,可在setUp()方法中创建一系列实例并设置它们的属性,再在测试方法中直接使用这些实例,相比较于每个测试方法中都创建实例并设置属性容易。
参考书籍:《Python编程从入门到实践》
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)