python文件和异常

目录

一、从文件中读取数据

二、写入文件

三、异常

四、存储数据


一、从文件中读取数据

1.读取整个文件 

创建一个pi_digits.txt的文件,将文件保存在程序所在的目录

3.1415926535
8979323846
2643383279

函数open( ),以任何方式使用文件,哪怕仅仅打印其中的内容,都要先打开文件,才能访问;接受一个参数:要打开的文件名称。python在当前执行的文件所在的目录中查找指定的文件。函数open()返回一个表示文件的对象,将该对象赋给file_object供以后使用。

关键字with在不需要访问文件后将其关闭,让Python负责妥善地打开和关闭文件。也可调用open( )和close( )来打开和关闭文件,但若程序存在bug导致方法close( )未执行,文件将不会关闭,未妥善关闭文件会导致数据丢失或受损;若过早调用close( )需要使用文件时已关闭,无法访问。

方法read( )读取文件的全部内容,将其作为一个常常的字符串赋给变量contents,打印值。

with open ('pi_digits.txt') as file_object:
	contents = file_object.read()
print(contents)
3.1415926535
8979323846
2643383279

相较原始文件,输出的末尾多了一个空行。原因:read( )到达文件末尾时会返回一个空字符串,空字符串显示出来就是一个空行,要删除多出来的空行,可使用rstrip( )

with open ('pi_digits.txt') as file_object:
	contents = file_object.read()
print(contents.rstrip())

2.文件路径

要让python打开不与程序文件位于同一目录中的文件,需提供文件路径,让python到特定位置查找

相对路径:程序文件在文件夹python_work中,文件夹python_work下的text_files的文件夹存储程序文件操作的文本文件file_object。

显示文件路径时,Windows系统使用反斜杠\,而不是斜杠/,代码中依然可用使用斜杠/

with open('text_files/filename.txt') as file_object

绝对路径:将文件在计算机中准确的位置告诉python。绝对路径较长,可将其赋给一个变量,再将变量传给open( ).

file_path = '/home/ehmatthes/other_files/text_files/filename.txt'
with open(file_path) as file_object

要么将数据存储在程序文件所在的目录或程序文件所在的目录下的一个文件夹

若在文件路径中直接使用反斜杠可能导致错误:C:\path\to\file.txt",其中的\t将被解读为制表符,可对路径中的每个反斜杠进行转译C:\\path\\to\\file.txt。

3.逐行读取(for循环)

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

使用关键词with可用让python负责妥善打开和关闭文件。

file_name = 'pi_digits.txt'   #将要读取的文件的名称赋给变量filename
with open (file_name) as file_object:   #将一个表示文件及内容的对象赋给变量file_object
	for line in file_object:
		print(line)
3.1415926535

8979323846

2643383279

空白行:每行的末尾都有一个看不见的换行符,而函数调用print()也会加上一个换行符,rstrip()

file_name = 'pi_digits.txt'
with open (file_name) as file_object:
	for line in file_object:
		print(line.rstrip())

4.创建一个包含文件各行内容的列表(在with( )代码块外使用 方法readlines( ))

使用关键字with,open( )返回的文件对象只在with代码块内使用,如何在with( )代码块外使用?在with代码块内将文件的各行存储在一个列表中,在with代码块外使用该列表。

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

file_name = 'pi_digits.txt'
with open (file_name) as file_object:
	lines = file_object.readlines()
for line in lines:
	print(line.rstrip())
3.1415926535
8979323846
2643383279

5.使用文件的内容(空字符,添加)

将文件读取到内存后,可以任何方式使用数据。先指定一个变量为空字符型,再加进去

file_name = 'pi_digits.txt'
with open (file_name) as file_object:
	lines = file_object.readlines()
pi_string = ''
for line in lines:
	pi_string += line.strip()
print(pi_string)
print(len(pi_string))
3.141592653589793238462643383279
32

读取文本文件时,python将所有文本都解读为字符串,若读取数且要以数值使用,函数int()将其转为整数、函数float()将其转为浮点型。

6.包含一百万位的大型文件

只打印到小数点后50位,对于可处理的数据量,Python没有任何限制,只要内存足够大。

file_name = 'pi_million_digits.txt'

with open (file_name) as file_object:
	lines = file_object.readlines()

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

print(f"{pi_string[:52]}...")
print(len(pi_string))
3.14159265358979323846264338327950288419716939937510...
1000002

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

file_name = 'pi_million_digits.txt'

with open (file_name) as file_object:
	lines = file_object.readlines()

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

birthday = input("Enter your birthday,in the form mmddyy: ")

if birthday in pi_string:
	print("Your birthday appears in the first million digits of pi!")
else:
	print("Your birthday does not appear in the first million digits of pi.")
Enter your birthday,in the form mmddyy: 060501
Your birthday appears in the first million digits of pi!

二、写入文件

open的第二个实参是可选的,文件对象的方法都是.write()

1.写入空文件('w')

将文本写入文件,再调用open( )时需提供另一个实参,告诉python 要写入打开的文件。第一个实参是要打开文件的名称,第二个实参'w'是告诉python以写入模式打开文件。

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

第二各参数:打开文件时可指定读取模式('r')、写入模式('w')、附加模式('a')、读写模式('r+'),若省略了模式实参,将以默认的只读模式打开文件。

第一个参数:若要写入的文件不存在,将自动创建;若已存在,再返回文件对象前会清空文件内容

file_name = 'programming.txt'
with open (file_name,'w') as file_object:
	file_object.write('I love programming.')

注意:python只能将字符串存入文本中,若要将数值存储在文本中,用函数str()转为字符串格式

2.写入多行(\n)

file_name = 'programming.txt'
with open (file_name,'w') as file_object:
	file_object.write('I love programming.')
	file_object.write('I love creating new games.')
I love programming.I love creating new games.

两行内容挤在一起,让每个字符串都单独占一行,在方法调用write()中包含换行符。

file_name = 'programming.txt'
with open (file_name,'w') as file_object:
	file_object.write('I love programming.\n')
	file_object.write('I love creating new games.\n')
I love programming.
I love creating new games.

3.附加到文件[open实参'a',.write]

给文件添加内容,可以附加模式打开文件,指定实参'a',将写入文件的行添加到文件末尾。

file_name = 'programming.txt'
with open (file_name,'a') as file_object:
	file_object.write('I also love finding meaning in large database.\n')
	file_object.write('I love creating apps that can run in a browser.\n')
I love programming.
I love creating new games.
I also love finding meaning in large database.
I love creating apps that can run in a browser.

三、异常

可使用try-except代码块处理的,让python执行指定的操作,同时告诉python发生异常时怎么办

1.处理ZeroDivisionError异常(try-except)

不能用数除以0,错误ZeroDivisionError是个异常对象,将停止运转程序

print(5/0)
Traceback (most recent call last):
  File "F:\python_work\chapter_10\division_calculator.py", line 1, in <module>
    print(5/0)
ZeroDivisionError: division by zero

认为可能发生错误时,编写一个try-except代码块来处理可能引发的异常。将可能有问题的放到try代码块中,如果没问题将跳过except代码块,如果有问题将执行except中的代码块。

try:
	print(5/0)
except ZeroDivisionError:
	print("You can't divide by zero!")
You can't divide by zero!

2.使用异常避免崩溃

发生错误时,若程序还有工程未完成,需妥善处理错误,这种情况经常出现在要求用户提供输入的程序中。

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: 10

second number: 0
Traceback (most recent call last):
  File "F:\python_work\chapter_10\division_calculator.py", line 11, in <module>
    answer = int(first_number)/int(second_number)
ZeroDivisionError: division by zero

3.else代码块(try-except-else)

当除数为0时,程序崩溃,有的人会糊涂,坏恶意的人可能会依据Traceback信息攻击。可以将可能隐藏错误的代码放到try-except代码块中

try-except-else代码块:try代码块中可能有问题,若try成功,执行else;若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("\nsecond number: ")
	if second_number == 'q':
		break
	
	try:
		answer = int(first_number)/int(second_number)
	except ZeroDivisionError:
		print("You can't division by 0!")
	else:
		print(answer)

4.处理FileNotFoundError异常(try-except)

找不到文件:文件可能在别的地方,文件名不对,文件不存在。都可使用try-except代码块处理。

filename = 'alice.txt'
with open(filename,encoding='utf-8') as f:
	contents = f.read()

 使用变量f来表示文件对象,这是一种常见做法。

参数encoding指定值,在系统默认编码与要读取文件使用编码不一致时(从古登堡计划中赋值粘贴的文件),必须这样做。

Traceback (most recent call last):
  File "F:\python_work\chapter_10\alice.py", line 2, in <module>
    with open(filename,encoding='utf-8') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'

python找不到文件的异常,时函数open导致的,可try语句放在open()之前

filename = 'alice.txt'
try:
	with open(filename,encoding='utf-8') as f:
		contents = f.read()
except FileNotFoundError:
	print(f"Sorry,the file {filename} does not exist.")
Sorry,the file alice.txt does not exist.

5.分析文本[.read()\.split( )\len( )]

可以分析包含整本书的文本文件,古登堡计划提供理论一系列不受版权限制的文学作品。

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

>>> title = 'Alice in Wonderland'
>>> title.split()
['Alice', 'in', 'Wonderland']

计算《爱丽丝漫游奇境记》包含多少个单词

filename = 'alice.txt'
try:
	with open(filename,encoding='utf-8') as f:
		contents = f.read()  #contents中包含童话书中的全部文本
except FileNotFoundError:
	print(f"Sorry,the file {filename} does not exist.")
else:
	words = contents.split() #包含童话书中所有单词的列表
	num_words = len(words)   #确定列表长度
	print(f"The file {filename} has about {num_words} words.")
The file alice.txt has about 30364 words.

这个数稍大点,因为包含出版商提供的额外信息。

6.使用多个文件(函数+for)

def count_words(filename):  #形参  
	"""计算一个文件大致包含多少个单词"""
	try:
		with open(filename,encoding='utf-8') as f:
			contents = f.read()
	except FileNotFoundError:
		print(f"Sorry,the file {filename} does not exist.")
	else:
		words = contents.split()
		num_words = len(words)
		print(f"The file {filename} has about {num_words} words.")

filename = 'alice.txt'
count_words(filename)       #实参 
The file alice.txt has about 30364 words.
def count_words(filename):    
	"""计算一个文件大致包含多少个单词"""
	try:
		with open(filename,encoding='utf-8') as f:
			contents = f.read()
	except FileNotFoundError:
		print(f"Sorry,the file {filename} does not exist.")
	else:
		words = contents.split()
		num_words = len(words)
		print(f"The file {filename} has about {num_words} words.")

filenames = ['alice.txt','siddhartha.txt','moby_dick.txt','little_women.txt']
for filename in filenames:
	count_words(filename)    
The file alice.txt has about 30364 words.
The file siddhartha.txt has about 42235 words.
Sorry,the file moby_dick.txt does not exist.
The file little_women.txt has about 176372 words.

使用try-except的优点:避免用户看到traceback,让程序继续分析能够找到的其他文件。

7.静默失败(pass语句)

在程序发生异常时保持静默,就像什么也没发生一样继续运行。可在try-except代码块中的except中明确告诉python什么都不要做。pass语句让python在代码块中什么都不要做。

def count_words(filename):    
	"""计算一个文件大致包含多少个单词"""
	try:
		with open(filename,encoding='utf-8') as f:
			contents = f.read()

	except FileNotFoundError:
		pass

	else:
		words = contents.split()
		num_words = len(words)
		print(f"The file {filename} has about {num_words} words.")

filenames = ['alice.txt','siddhartha.txt','moby_dick.txt','little_women.txt']
for filename in filenames:
	count_words(filename) 
The file alice.txt has about 30364 words.
The file siddhartha.txt has about 42235 words.
The file little_women.txt has about 176372 words.

将找不到的文件名称写入另一个文件中,用户看不到,但我们可以读取。

8.决定报告哪些错误

python的错误处理结构让你能细致的控制与用户分享错误信息的程度。

编写的好且经过详尽测试的代码不容易出现内部错误,如语法错误。但只要程序依赖于外部错误,如用户输入、存在指定性文件、有网络链接就可能出现异常。

四、存储数据

很多程序都要用户输入某种信息,程序都把信息存储在字典或列表中,关闭程序时要保存他们提供的信息,使用模块json来存储数据,模块json能将简单的数据结构转储到文件中,并在程序再次运行时加载文件中的数据;可以程序之间分享数据;可与其他使用编程语言的人分享。

JSON:JavaScript Object Notation,最初由JavaScript开发,随后成了一种常见格式。

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

函数json.dump( )接受两个参数:内容的变量名、存内容的文件名。程序无输出,但可打开文件查看内容。

import json                        #导入模块
numbers = [2,3,5,7,11,13]          #创建数字列表
filename = 'number.json'           #指出将列表存储在哪个文件中,.json为文件存储的数据格式
with open (filename,'w') as f:     #以写入模式打开
	json.dump(numbers,f)           #将列表内容存储到f文件中
[2, 3, 5, 7, 11, 13]

使用函数json.load( ),包括一个参数:要打开文件名。将列表读取到内存中。这是一种在程序之间共享数据的简单方式。

import json
filename = 'number.json'          
with open (filename) as f:
	numbers = json.load(f)
	print(numbers)
[2, 3, 5, 7, 11, 13]

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

使用json存储用户生成的数据,可防止用户的信息在程序停止时丢失。

提示用户首次运行程序时输入自己的名字,并在再次运行程序时记住。

import json
username = input("What's your name?" )
filename = 'username.json'
with open (filename,'w') as f:
	json.dump(username,f)
	print(f"We'll remember you when you come back,{username}!")
What's your name?Eric
We'll remember you when you come back,Eric!

读取用户生成的数据

import json
filename = 'username.json'
with open(filename) as f:
	username = json.load(f)
	print(f"Welcome back, {username}!")
Welcome back, Eric!

两程序合二为一,先尝试从文件中获取用户名,若没有,提示用户输入再存储,

import json
#如果已经存储了用户名,加载;否则提示输入并存储
filename = 'username.json'
try:
	with open (filename) as f:    #尝试打开文件filename,即username.json
		username = json.load(f)   #若文件存在,将其中的用户名读取到内存中,再执行else中的内容

except FileNotFoundError:         #若文件不存在,将引发异常
	username = input("What's your name? ")   #提示用户输入
	with open(filename,'w') as f:            #以写入模式打开文件(之前可以不存在)
		json.dump(username,f)                #json.dump()存储用户名
		print(f"We will remember you when you come back,{username}!")  #打印一句问候语

else:
	print(f"Welcome back,{username}!")
Welcome back,Eric!
What's your name? Eric
We will remember you when you come back,Eric!

3.重构

代码能正常运行,但通过将其划分为一系列完成具体工作的函数,还可改进,这一过程称为重构。

import json

def greet_user():
	"""问候用户,并指出其名字"""
	filename = 'username.json'
	try:
		with open (filename) as f:
			username = json.load(f)
	except FileNotFoundError:
		username = input("What's your name? ")
		with open(filename,'w') as f:
			json.dump(username,f)
			print(f"We will remember you when you come back,{username}!")
	else:
		print(f"Welcome back,{username}!")

greet_user()

使用一个函数,将原有注释删掉,使用文档字符串来指出程序作用。

import json

def get_stored_name():
"""如果存储了用户名,就获取它"""
	filename = 'username.json'
	try:
		with open (filename) as f:
			username = json.load(f)
	except FileNotFoundError:
		return None      #如果文件不存在就返回None
	else:
		return username

def greet_user():
"""问候用户,并指出其名字"""
	username = get_stored_name()
	if username:
		print(f"Welcome,{username}")
	else:
		username = input("What's your name? ")
		with open(filename,'w') as f:
			json.dump(username,f)
			print(f"We will remember you when you come back,{username}!")

greet_user()

使用3个函数,每个函数都执行单一而清晰的任务。在调用greet_user( )时,首先调用get_stored_username( ),最后在必要时调用get_new_username( )

import json

def get_stored_name():
	"""如果存储了用户名,就获取它"""
	filename = 'username.json'
	try:
		with open (filename) as f:
			username = json.load(f)
	except FileNotFoundError:
		return None 
	else:
		return username

def get_new_user():
	"""提示用户输入用户名"""
	username = input("What's your name? ")
	filename = 'username.json'
	with open(filename,'w') as f:
		json.dump(username,f)
		return username

def greet_user():
	"""问候用户,并指出其名字"""
	username = get_stored_name()
	if username:
		print(f"Welcome,{username}")
	else:
		username = get_new_user()
		print(f"We will remember you when you come back,{username}!")

greet_user()

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值