python基础8-文件和异常
8.1、从文件中读取数据
要使用文本文件中的信息,首先需要将信息读取到内存中,为此,可以选择一次行读取文件的全部内容,也可以以每次一行的方式逐步读取。
8.1.1、读取整个文件
要以任何方式使用文件,都要先打开文,这样才能访问。
open()
接受一个参数,表示要打开文件的文件名
with
在不再需要访问文件后将其关闭
在这个例子中,没有使用close()来关闭文件,但是可以调用open()和close()来打开和关闭文件,但是如果这样做的话,如果程序存在bug,导致close()语句未执行,文件将不会关闭,未妥善关闭文件会导致数据丢失或受损。
通过这种结构,可以让Python去决定什么时候讲文件关闭
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
输出结果会多一个空行,因为read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行,可以在print语句中使用rstrip()来消除空行
8.1.2、文件路径
python只会在文件夹中找,而不会在其子文件夹中查找,因此要让python打开不与程序文件位于同一个目录中的文件,需要提供文件路径。
- linux中使用斜杠
/
- windows中使用反斜杠
\
8.1.3、逐行读取
读取文件是,常常需要检查其中的每一行:你可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。
每行的末尾都有一个看不见的换行符,而print语句也会加上一个换行符,因此每行末尾都有两个换行符,可在Print语句中使用rstrip()函数来消除换行符
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line)
8.1.4、创建一个包含文件各行内容的列表
使用关键字with是,open()返回的文件对象只能在with代码块中使用。如果要在with代码外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表
ef read_file_on_line(filename):
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
filename = 'pi_digits.txt'
read_file_on_line(filename)
8.1.5、使用文件的内容
将文件读取到内存中后,就可以以任何方式使用这些数据了。
python将文本内容都解读为字符串,如果读取的是数字,需要使用int()或者float()函数将其转换为浮点数
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))
8.1.6、包含一百万位的大型文件
在文件中有大量数据时,可以使用列表截取的方式来读取随机位置的有限位文本
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[:52] + "...")
print(len(pi_string))
8.2、写入文件
8.2.1、写入空文件
需要将文本写入文件,在调用open()时需要提供另一个实参,表示要往打开的文件中写入文本数据。
在这个实例中,调用open()时,提供了两个实参,第一个是打开文件的名称,第二个实参表示要以写入模式打开这个文件。
打开文件有以下几种模式:
- 读取模式 'r' (默认只读取)
- 写入模式 'w'
- 附加模式 'a'
- 读取和写入文件 'r+'
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
8.2.2、写入多行
函数write不会在写入的文本末尾添加换行符,所以如果需要写入多行的话,注意使用'\n'换行符来换行
像显示到终端的输出一样,还可以使用空格,制表符和空行来设置这些输出的格式
def write_file(filename, str):
# write back to file
with open(filename, 'w') as file_object:
file_object.write(str)
str = 'I love programming.\n'
str += 'I love creating new games.\n'
write_file('programming.txt', str)
8.2.3、在文件中追加内容
如果要在文件末尾添加内容,而非覆盖原有的内容,可以使用附加模式打开文件,这种模式下,python不会在返回文件对象前清空文件,而将新写入的内容都追加到文件末尾。
def write_file(filename, str):
# write back to file
with open(filename, 'a') as file_object:
file_object.write(str)
str = 'I love programming.\n'
str += 'I love creating new games.\n'
write_file('programming.txt', str)
8.3、异常
python使用异常的特殊对象来管理程序执行期间发生的错误,当出现错误时,python会创建一个异常对象。如果在程序中对异常对象进行处理,则程序会继续运行,否在程序将停止,并显示一个traceback,其中包含有关异常的报告。
异常是使用try-except代码块处理的。
8.3.1、处理ZeroDivisionErro异常
除法运算,除数如果是0,就会报该错误
try:
print(5/0)
expect ZeroDivisionError:
print("You can`t divide by zero!")
8.3.2、使用异常避免崩溃
print("Give me two numbers, and I`ll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number:\n")
if first_number == 'q':
break
second_number = input("\nSecond number:\n")
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can`t divide by zero\n")
continue
print(answer)
8.3.3、else代码块
执行错误的情况放在try-except代码块中,将依赖于try代码块成功执行的代码应放到else中。代码流程如下:
- python尝试执行try中的代码,只有可能引发异常的代码才放到try代码块中
- 如果运行异常,则看异常的类型是否包含在except中,如果是,则执行except代码块中代码
- 如果运行正常,则执行else中代码
print("Give me two numbers, and I`ll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number:\n")
if first_number == 'q':
break
second_number = input("\nSecond number:\n")
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can`t divide by zero\n")
continue
else:
print(answer)
8.3.4、处理FileNotFoundError异常
FileNotFoundError异常通常是由于找不到文件所引起的
filename = 'alice.txt'
try:
with open(filename) as file_obj:
contents = file_obj.read()
except FileNotFoundError:
msg = 'Sorry, the file ' + filename + " does not exist."
print(msg)
8.3.5、分析文本
分析包含整本书的文本内容
split()方法根据字符串创建一个单词列表,使用该方法一空格为分隔符将字符串拆分为多个部分,并将这部分存储到一个列表中。
filename = 'atom.txt'
try:
with open(filename) as file_obj:
contents = file_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.")
8.4、存储数据
程序把客户提供的信息存储在列表和字典等数据结构中,当用户关闭程序是,需要保存这些信息,可以使用模块json来存储数据
8.4.1、json.dump()和json.load()
使用json.dump()将数据存储在文件中,使用json.load()将文件内容读取到内存中
Json.dump()有两个参数:
- 要存储的数据
- 可用于存储数据的文件对象
import json
numbers = [2, 3, 4, 5, 8, 21]
filename = 'numbers.json'
with open(filename, 'w') as file_obj:
json.dump(numbers, file_obj)
with open(filename) as file_obj:
numbers = json.load(file_obj)
print(numbers)
8.4.2、保存和读取用户生成的数据
对于用户生成的数据,使用json保存他们大有裨益。
import json
filename = 'username.json'
def save_user_name(filename):
username = input("what`s your name?")
with open(filename, 'w') as file_obj:
json.dump(username, file_obj)
print("we`ll remember you when you come back, " + username + "!")
def greet_user(filename):
with open(filename) as file_obj:
username = json.load(file_obj)
print("hello, " + username)
save_user_name(filename)
greet_user(filename)
8.4.3、重构
代码可以正确地运行,但是可做进一步的改进——将代码划分为一系列完成具体工作的函数,这样的过程被称为重构。重构让代码更清晰,更易于理解,更容易扩展