Python基础入门6_文件和异常

Python 基础入门前五篇:

  • Python 基础入门–简介和环境配置
  • Python基础入门_2基础语法和变量类型
  • Python基础入门_3条件语句和迭代循环
  • Python基础入门_4函数
  • Python基础入门_5面向对象基础

这次将介绍有关文件和异常的处理,包括读写文本文件、二进制文件、JSON 文件,异常处理,以及 pathlib 模块的介绍。

本文的目录如下:


1. 文件

简介

Python 中读取、写入文件,都可以通过方法 open() 实现,该方法用于打开一个文件,然后返回文件对象,如果文件不存在或者无法打开,会报错 OSError

open 方法的语法如下:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

几个参数说明:

  • file:必需,文件路径,相对或者绝对路径皆可;
  • mode:可选,文件打开的模式
  • buffering:设置缓冲
  • encoding:一般采用 utf8
  • errors:报错级别
  • newline:区分换行符
  • closefd:传入的 file 参数类型

常用的文件打开模式如下:

操作模式具体含义
r读取(默认文件打开模式)
w写入(会截断前面的内容)
x写入,如果文件已经存在会产生异常
a追加,将内容写入到已有文件末尾
b二进制模式
t文本模式(默认)
+更新(既可以读又可以写)

其中 rwa 是三选一,表明读取或者写入,然后可以添加其他几种模型,即还存在:

  • rb , r+, rb+
  • wb, w+, wb+
  • ab, a+, ab+

对于 open 方法返回的 file 文件对象,它常用函数有:

  • close():关闭文件
  • flush():将内部缓冲区数据立刻写入文件
  • read([size]):从文件读取指定的字节数,如果没有或者是负数值,则读取所有
  • readline():读取整行,包含换行符 \n 字符
  • readlines([sizeint]):读取所有行并返回列表,若给定 sizeint>0,返回总和大约为 sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。
  • write(str):将字符串写入文件,返回的是写入字符的长度
  • writelines(sequence):向文件写入一个序列字符串列表,如果需要换行,需要自己添加每行的换行符
  • seek(offset[, whence]):设置文件当前位置
  • tell():返回文件当前位置。
  • truncate([size]:从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 Windows 系统下的换行代表 2个字符大小。

读取文本文件

读取文本文件,必须传入文件路径,然后打开模式指定为 r ,接着就就是通过 encoding 参数指定编码,当然不设置这个编码参数,它默认值是 None ,读取文件将采用操作系统默认的编码,通常如果文件内容不带有中文,这种方法是没问题的,如果带有中文内容,则必须指定 encoding='utf8' 才能正常打开文件。

以下是一个使用例子:

# 方法1
f = open('test.txt', 'r')
print(f.read())
f.close()

输出结果:

life is short, I use Python.
Machine Learning
Computer Vision

这是第一种使用方法,这种方法的问题就是如果忘记调用 close 方法关闭文件,会出现错误,因此推荐使用上下文语法,通过 with 关键字指定文件对象的上下文环境并在离开上下文环境时自动释放文件资源,此外,读取文件内容,可以直接调用 read() 方法,也可以采用 for-in 循环读取:

# 方法2
with open('test.txt', 'r') as fr:print(fr.read())
# 方法3 读取文件也可以采用 for-in 循环逐行读取
with open('test.txt', 'r') as fr:for line in fr:print(line.strip())

2. 异常

Python 有两种错误很容易辨认:语法错误和异常

语法错误也称为解析错,比如下面这个例子:

while Trueprint('hello')

会报错误,这里指出语法错误的地方,就是缺少非常重要的冒号 :

File "<ipython-input-41-b385275d6655>", line 1while True^
SyntaxError: invalid syntax

而异常,是运行期检测到的错误,即解析成功后,开始运行时的错误,比如执行除法操作时候,除数是 0 的情况;读取文件的时候,文件路径错误;变量没有定义的情况等等。

异常处理

异常的处理,就是采用 try-exception 语句,例子如下:

def read_file(file_name):file_contents = Nonetry:with open(file_name, 'r', encoding='utf-8') as f:file_contents = f.read()except FileNotFoundError:print('无法打开指定的文件!')except LookupError:print('指定了未知的编码!')except UnicodeDecodeError:print('读取文件时解码错误!')else:print('读取文件成功')finally:print('程序执行完毕')return file_contents

上述代码中,try 语句是这样执行的:

  • 先执行 try 语句,即 tryexcept 之间的句子
  • 如果没有异常发生,就忽略 except ,然后按顺序执行 else 语句,finally 语句
  • 如果发生异常,那就忽略 try 语句中发生异常部分后面的代码,然后执行和异常类型一样的 except 语句,之后执行 finally 语句
  • 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。

一个 try 语句可能包含多个 except 子句,分别来处理不同的特定的异常。最多只有一个分支会被执行

处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。

一个 except 子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

except (FileNotFoundError, LookupError, UnicodeDecodeError) as e:print(e)

上述情况,可以添加一个 except 语句,忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出,如下所示:

import sysdef read_file2(file_name):file_contents = Nonetry:with open(file_name, 'r', encoding='utf-8') as f:file_contents = f.read()except (LookupError, UnicodeDecodeError) as e:print(e)except:print('发生了未知的错误', sys.exc_info()[0])else:print('读取文件成功')finally:print('程序执行完毕')return file_contents

不过,其实还有一种比较偷懒的写法,直接用 Exception 捕获所有异常:

import sys
def read_file3(file_name):file_contents = Nonetry:with open(file_name, 'r', encoding='utf-8') as f:file_contents = f.read()except Exception as e:print(e)else:print('读取文件成功')finally:print('程序执行完毕')return file_contents

当然,推荐的写法还是前面几种写法,这样可以针对不同异常情况有不同的做法。

另外,这里的 else 语句是 try 语句执行成功后,继续执行的语句,而 finally 则是无论是否发生异常,都会执行的语句,它是定义了无论任何情况都会执行的清理行为

有一些方法是有预定义的清理行为,比如说上述说到的关键词 with 语句,就定义了无论文件操作如何,都会执行关闭文件对象的行为

这两个语句是可选择的,不是使用的语句。

抛出异常

上述的异常处理,在出现异常后,是可以继续执行后续的代码(try-exception 后面的语句),即不会终止程序的执行,但如果希望发生异常就终止程序运行,可以采用 raise 关键字,如下代码所示:

try:with open(file_name, 'r', encoding='utf-8') as f:file_contents = f.read()
except Exception as e:print(e)raise

或者如下所示,raise 后面加上指定的异常名称和参数

raise NameError('HiThere')

最后,更多异常处理的例子可以查看 《总结:Python中的异常处理》,文章给出了关于异常的最佳实践:

  1. 只处理你知道的异常,避免捕获所有异常然后吞掉它们。
  2. 抛出的异常应该说明原因,有时候你知道异常类型也猜不出所以然。
  3. 避免在 catch 语句块中干一些没意义的事情,捕获异常也是需要成本的
  4. 不要使用异常来控制流程,那样你的程序会无比难懂和难维护。
  5. 如果有需要,切记使用 finally 来释放资源
  6. 如果有需要,请不要忘记在处理异常后做清理工作或者回滚操作

3. 更多文件和异常的例子

介绍完文件和异常,接下来介绍更多的文件操作,搭配异常处理。

写入文件

写入文件,只需要设置文件打开模式是写入模型,即 w ,代码例子如下所示,这里实现读取一个文件的内容,然后写入到一个新的文件中。

def save_to_file(input_file, outputfile, write_mode='w'):file_contents = read_file(input_file)try:with open(outputfile, write_mode, encoding='utf-8') as fw:fw.write(file_contents)except IOError as ioerror:print(ioerror)print('写入文件出错')
input_file = 'test.txt'
output_file= 'new_test.txt'
save_to_file(input_file, output_file, write_mode='w')

读取二进制文件

读写文本文件的例子都有了,接下来就是二进制文件的读取和写入,这里实现一个复制图片文件的功能,如下所示,读取和保存图片时候,采用的文件模型分别是 rbwb

def copy_image_file(input_image, output_image):try:with open(input_image, 'rb') as img1:data = img1.read()print(type(data))with open(output_image, 'wb') as out:out.write(data)except FileNotFoundError as e:print('指定的文件无法打开--{}'.format(input_image))except IOError as e:print('读写文件出现错误')finally:print('程序执行结束')

使用例子:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
input_image = 'example.jpg'
output_image = 'copyed.jpg'
copy_image_file(input_image, output_image)

采用的用于复制的图片如下所示:

这里,在 jupyter notebook 中展示图片的代码如下:

%matplotlib inline
img = Image.open(input_image)
print(np.asarray(img, dtype=np.uint8).shape)
plt.imshow(img);

这里最好一行代码 plt.imshow(img),如果不加分号,会输出图片变量的信息,即 <matplotlib.image.AxesImage at 0x1d0d1161dd8>,然后再显示图片,而加分号,则直接显示图片。

读写 JSON 文件

上述介绍了如何保存文本数据和二进制数据到文件中,但如果我们希望保存的是列表或者字典的数据,那么可以选择采用 JSON 格式。

JSONJavaScript Object Notion 的缩写,现在广泛应用于跨平台跨语言的数据交换,因为它是纯文本,任何编程语言都可以狐狸纯文本。更多关于它的介绍,可以查看官网–http://json.org/

JSON 的数据类型和 Python 数据类型的对应关系分别如下面两张表所示:

JSON->Python:

JSONPython
objectdict
arraylist
stringstr
number(int / real)int / float
true / falseTrue / False
nullNone

Python->JSON

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumber
True / Falsetrue / false
Nonenull

在 Python 中,使用 json 库就可以保存或者读取 JSON 格式的文件,代码例子如下:

import json
# 先生成一个json文件
test_dict = {'name': 'python','age': 40,'package': ['os', 'json', 'sys'],'features': {'data_analysis': ['pandas', 'matplotlib'],'deep_learning': ['scikit-learn', 'tensorflow', 'pytorch', 'keras']}
}
try:with open('test_data.json', 'w', encoding='utf-8') as fw:json.dump(test_dict, fw, indent=4, separators=(',', ': '))
except IOError as e:print(e)
finally:print('程序执行完毕')

这是一个保存为 JSON 文件的代码,调用 dump() 方法,然后读取代码如下所示:

# 读取 json 文件
try:with open('test_data.json', 'r') as fr:contents = json.load(fr)for key, val in contents.items():print('{}: {}'.format(key, val))
except IOError as e:print(e)
print('读取完毕')

这里调用方法 load() 方法。

json 库中比较重要的是下面四个方法:

  • dump :将 Python 对象按照 JSON 格式序列化到文件中
  • dumps :将 Python 对象处理为 JSON 格式的字符串
  • load:将文件中的 JSON 数据反序列化为 Python 对象
  • loads:将字符串内容反序列化为 Python 对象

这里面,只要方法以 s 结尾,那就是和字符串有关系,而如果不带,那就是和文件有关系了。

这里的序列化和反序列化,其中序列化就是指将数据结果或者对象状态转换为可以存储或者传输的形式,也就是一系列字节的形式,而从这些字节提取数据结构的操作,就是反序列化。

在 Python 中,序列化和反序列化还可以采用 pickleshelve 两个库,但它们仅适用于 Python,不能跨语言。

删除文件或者文件夹

对于删除文件,可以采用这两种方法,分别用到 ospathlib 两个模块

  • os.remove()
  • pathlib.Path.unlink() ,这个方法也可以删除链接

删除文件夹有三种方法,不过前两者都只能删除空文件夹

  • os.rmdir() 只能删除空的文件夹
  • pathlib.Path.rmdir() 删除空文件夹
  • shutil.rmtree() 可以删除非空文件夹

4. pathlib 模块

最后介绍一个在 Python 3.4 版本加入的新模块–pathlib ,这是一个可以很好处理文件相关操作的模块。

首先对于文件路径,最大的问题可能就是 Unix 系统和 Windows 系统采用的斜杠不同,前者是 / ,而后者是 \ ,因此之前的处理文件路径拼接的方式,可以采用 os.path.join 方法,例如:

data_folder = 'source_folder/python/'
file_path = os.path.join(data_folder, 'abc.txt')
print(file_path)
# 输出 source_folder/python/abc.txt

但现在有了一个更加简洁的方法,就是采用 pathlib 模块的 Path 方法,如下所示:

from pathlib import Path
data_folder = Path('source_folder/python/')
file_path = data_folder / 'abc.txt'
print(file_path)
# 输出 source_folder\python\abc.txt

需要注意两件事情:

  1. 采用 pathlib 的方法,应该使用 / 斜杠Path() 方法会自动根据当前系统修改斜杠,比如上述例子就更改为 Windows\\
  2. 文件路径的拼接,直接采用 / 即可,不需要再写成 os.path.join(a,b) ,更加方便简洁。

当然,pathlib 并不只是有这个用途,它还可以完成更多事情:

读取文件内容不需要打开和关闭文件,如下所示,直接调用 read_text 方法即可读取内容

data_folder = Path('./')
file_path = data_folder / 'test.txt'
print(file_path.read_text())

pathlib 可以更加快速容易实现大部分标准的文件操作,如下所示,分别执行打印文件路径,文件后缀,文件名(不包含文件后缀部分)、判断文件是否存在的四个操作。

filename = Path('./test.txt')
print(filename.name) # 输出 test.txt
print(filename.suffix) # 输出 .txt
print(filename.stem)   # 输出 testif not filename.exists():print('file does not exist!')
else:print('file exists')

可以显式将 Unix 路径转换为 Windows 形式的:

from pathlib import PureWindowsPath
filename = Path('source/test.txt')
path_on_windows = PureWindowsPath(filename)
print(path_on_windows) # 输出 source\test.txt

当然,对于上述代码,如果希望安全的处理斜杠,可以显式定义为 Windows 格式的路径,然后 pathlib 会将其转换为可以在当前系统使用的形式:

filename = PureWindowsPath('source/test.txt')
correct_path = Path(filename)
print(correct_path)
# 在 windows 输出 source\test.txt
# 在 Mac/Linux 输出 source/test.txt

最后,还可以利用 pathlib 将相对路径的文件解析生成如 file:// 形式的 urls,如下所示:

import webbrowser
filename = Path('./test.txt')
webbrowser.open(filename.absolute().as_uri())

当然,pathlib 的用法还有不少,更多的用法可以查看官网的介绍:

https://docs.python.org/3/library/pathlib.html


参考

  • Python3 File(文件) 方法
  • Python3 错误和异常
  • Day11–文件和异常
  • JSON 的官方网站
  • 《总结:Python中的异常处理》
  • https://stackoverflow.com/questions/6996603/delete-a-file-or-folder
  • https://medium.com/@ageitgey/python-3-quick-tip-the-easy-way-to-deal-with-file-paths-on-windows-mac-and-linux-11a072b58d5f
  • https://docs.python.org/3/library/pathlib.html

小结

本文简单介绍 Python 文件和异常的知识点,如何读写文本文件、二进制文件和 json 文件,然后异常处理,最后介绍一个新的处理文件相关操作的模块 pathlib .

此外,本文的代码都上传到我的 github 上了:

https://github.com/ccc013/Python_Notes/blob/master/Practise/file_and_exception_example.ipynb

欢迎关注我的微信公众号–算法猿的成长,或者扫描下方的二维码,大家一起交流,学习和进步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/408605.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

必读的10篇关于GAN的论文

前言 上次写的文章-- 一文了解下 GANs可以做到的事情&#xff0c;如果想进一步了解 GAN&#xff0c;学习研究 GAN&#xff0c;可以先从这 10 篇论文开始。 本文翻译自&#xff1a; https://towardsdatascience.com/must-read-papers-on-gans-b665bbae3317 原文介绍 10 篇介…

ArcGIS Server for JavaScript 3.3 的安装部署

一、安装包下载 首先从官网下载ArcGIS API for JavaScript 3.3 的API 和SDK&#xff0c;地址&#xff1a;http://support.esrichina.com.cn/2011/0223/960.html&#xff0c;需要注意的是&#xff0c;想获取API和SDK&#xff0c;需要注册一个Esri全球账户。 点击Library和SDK下载…

实战|手把手教你训练一个基于Keras的多标签图像分类器

图片来自 pexels&#xff0c;作者&#xff1a;Jean-Christophe Andr2019 年第 63 篇文章&#xff0c;总第 87 篇文章原文链接&#xff1a;https://www.pyimagesearch.com/2018/05/07/multi-label-classification-with-keras/作者&#xff1a;Adrian Rosebrock今天介绍的是基于 …

poj 2182 Lost Cows 解题报告

题意&#xff1a;每个奶牛都有一个编号&#xff0c;1- N 从第二个牛开始给出前面比她编号小的牛的个数&#xff0c;问你求牛的编号序列 解题思路:线段树 二分查找 (多个相同的数二分边界问题需要注意)  解题代码&#xff1a; 1 #include <stdlib.h>2 #include <stri…

基于Keras的多标签图像分类

原文链接&#xff1a;https://www.pyimagesearch.com/2018/05/07/multi-label-classification-with-keras/ 作者&#xff1a;Adrian Rosebrock 今天介绍的是基于 Keras 实现多标签图像分类&#xff0c;主要分为四个部分&#xff1a; 介绍采用的多标签数据集简单介绍使用的网…

快速入门 Jupyter notebook

2019 年第 64 篇文章&#xff0c;总第 88 篇文章本文大约 6400 字&#xff0c;阅读大约需要 17 分钟原文链接&#xff1a;https://www.dataquest.io/blog/jupyter-notebook-tutorial/Jupyter notebook 是一个很强大的交互式和展示数据科学项目的工具&#xff0c;它可以作为一个…

简单ORACLE分区表、分区索引

一段听说CSDN.COM里面很多好东西&#xff0c;同事建议看看合适自己也可以写一写&#xff0c;呵呵&#xff0c;今天第一次开通博客&#xff0c;随便写点东西&#xff0c;就以第一印象分区表简单写第一个吧。 ORACLE对于分区表方式其实就是将表分段存储&#xff0c;一般普通表格是…

【进程】进程通信-信号方式(中断)

信号方式(中断) 信号的基本概念 每个信号都对应一个正整数常量(称为signal number,即信号编号。定义在系统头文件<signal.h>中)&#xff0c;代表同一用户的诸进程之间传送事先约定的信息的类型&#xff0c;用于通知某进程发生了某异常事件。每个进程在运行时&#xff0c…

Jupyter notebook 入门教程

原文链接&#xff1a;https://www.dataquest.io/blog/jupyter-notebook-tutorial/ Jupyter notebook 是一个很强大的交互式和展示数据科学项目的工具&#xff0c;它可以作为一个开发文档&#xff0c;包含代码、解释说明文字、代码运行结果、数学公式等等&#xff0c;功能非常强…

【图像分类】细粒度图像分类是什么,有什么方法,发展的怎么样

欢迎大家来自《图像分类》专栏&#xff0c;今天讲述细粒度图像分类问题&#xff0c;这是计算机视觉领域一项极具挑战的研究课题&#xff0c;本文介绍了细粒度图像分类算法的发展现状、相关数据集和竞赛&#xff0c;供大家参考学习。作者 | 郭冰洋编辑 | 言有三1 简介细粒度图像…

Jupyter 进阶教程

2019 年第 65 篇文章&#xff0c;总第 89 篇文章本文大约 7500 字&#xff0c;建议收藏阅读原题 | Tutorial: Advanced Jupyter Notebooks作者 | Benjamin Pryke译者 | kbsc13("算法猿的成长"公众号作者)原文 | https://www.dataquest.io/blog/advanced-jupyter-note…