10 - Python文件编程和异常

news2024/11/23 7:57:15

文件和异常

在实际开发中,常常需要对程序中的数据进行持久化操作,而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词,可能需要先科普一下关于文件系统的知识,对于这个概念,维基百科上给出了很好的诠释,这里不再浪费笔墨。

在Python中实现文件的读写操作其实非常简单,通过Python内置的open函数,我们可以指定文件名、操作模式、编码信息等来获得操作文件的对象,接下来就可以对文件进行读写操作了。这里所说的操作模式是指要打开什么样的文件(字符文件还是二进制文件)以及做什么样的操作(读、写还是追加),具体的如下表所示。

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

下面这张图来自于菜鸟教程网站,它展示了如果根据应用程序的需要来设置操作模式。

在这里插入图片描述

读写文本文件

读取文本文件时,需要在使用open函数时指定好带路径的文件名(可以使用相对路径或绝对路径)并将文件模式设置为'r'(如果不指定,默认值也是'r'),然后通过encoding参数指定编码(如果不指定,默认值是None,那么在读取文件时使用的是操作系统默认的编码),如果不能保证保存文件时使用的编码方式与encoding参数指定的编码方式是一致的,那么就可能因无法解码字符而导致读取失败。下面的例子演示了如何读取一个纯文本文件。

def main():
    f = open('致橡树.txt', 'r', encoding='utf-8')
    print(f.read())
    f.close()


if __name__ == '__main__':
    main()

请注意上面的代码,如果open函数指定的文件并不存在或者无法打开,那么将引发异常状况导致程序崩溃。为了让代码有一定的健壮性和容错性,我们可以使用Python的异常机制对可能在运行时发生状况的代码进行适当的处理,如下所示。

def main():
    f = None
    try:
        f = open('致橡树.txt', 'r', encoding='utf-8')
        print(f.read())
    except FileNotFoundError:
        print('无法打开指定的文件!')
    except LookupError:
        print('指定了未知的编码!')
    except UnicodeDecodeError:
        print('读取文件时解码错误!')
    finally:
        if f:
            f.close()


if __name__ == '__main__':
    main()

在Python中,我们可以将那些在运行时可能会出现状况的代码放在try代码块中,在try代码块的后面可以跟上一个或多个except来捕获可能出现的异常状况。例如在上面读取文件的过程中,文件找不到会引发FileNotFoundError,指定了未知的编码会引发LookupError,而如果读取文件时无法按指定方式解码会引发UnicodeDecodeError,我们在try后面跟上了三个except分别处理这三种不同的异常状况。最后我们使用finally代码块来关闭打开的文件,释放掉程序中获取的外部资源,由于finally块的代码不论程序正常还是异常都会执行到(甚至是调用了sys模块的exit函数退出Python环境,finally块都会被执行,因为exit函数实质上是引发了SystemExit异常),因此我们通常把finally块称为“总是执行代码块”,它最适合用来做释放外部资源的操作。如果不愿意在finally代码块中关闭文件对象释放资源,也可以使用上下文语法,通过with关键字指定文件对象的上下文环境并在离开上下文环境时自动释放文件资源,代码如下所示。

def main():
    try:
        with open('致橡树.txt', 'r', encoding='utf-8') as f:
            print(f.read())
    except FileNotFoundError:
        print('无法打开指定的文件!')
    except LookupError:
        print('指定了未知的编码!')
    except UnicodeDecodeError:
        print('读取文件时解码错误!')


if __name__ == '__main__':
    main()

除了使用文件对象的read方法读取文件之外,还可以使用for-in循环逐行读取或者用readlines方法将文件按行读取到一个列表容器中,代码如下所示。

import time


def main():
    # 一次性读取整个文件内容
    with open('致橡树.txt', 'r', encoding='utf-8') as f:
        print(f.read())

    # 通过for-in循环逐行读取
    with open('致橡树.txt', mode='r') as f:
        for line in f:
            print(line, end='')
            time.sleep(0.5)
    print()

    # 读取文件按行读取到列表中
    with open('致橡树.txt') as f:
        lines = f.readlines()
    print(lines)
    

if __name__ == '__main__':
    main()

要将文本信息写入文件文件也非常简单,在使用open函数时指定好文件名并将文件模式设置为'w'即可。注意如果需要对文件内容进行追加式写入,应该将模式设置为'a'。如果要写入的文件不存在会自动创建文件而不是引发异常。下面的例子演示了如何将1-9999直接的素数分别写入三个文件中(1-99之间的素数保存在a.txt中,100-999之间的素数保存在b.txt中,1000-9999之间的素数保存在c.txt中)。

from math import sqrt


def is_prime(n):
    """判断素数的函数"""
    assert n > 0
    for factor in range(2, int(sqrt(n)) + 1):
        if n % factor == 0:
            return False
    return True if n != 1 else False


def main():
    filenames = ('a.txt', 'b.txt', 'c.txt')
    fs_list = []
    try:
        for filename in filenames:
            fs_list.append(open(filename, 'w', encoding='utf-8'))
        for number in range(1, 10000):
            if is_prime(number):
                if number < 100:
                    fs_list[0].write(str(number) + '\n')
                elif number < 1000:
                    fs_list[1].write(str(number) + '\n')
                else:
                    fs_list[2].write(str(number) + '\n')
    except IOError as ex:
        print(ex)
        print('写文件时发生错误!')
    finally:
        for fs in fs_list:
            fs.close()
    print('操作完成!')


if __name__ == '__main__':
    main()

读写二进制文件

知道了如何读写文本文件要读写二进制文件也就很简单了,下面的代码实现了复制图片文件的功能。

def main():
    try:
        with open('guido.jpg', 'rb') as fs1:
            data = fs1.read()
            print(type(data))  # <class 'bytes'>
        with open('吉多.jpg', 'wb') as fs2:
            fs2.write(data)
    except FileNotFoundError as e:
        print('指定的文件无法打开.')
    except IOError as e:
        print('读写文件时出现错误.')
    print('程序执行结束.')


if __name__ == '__main__':
    main()

读写JSON文件

通过上面的讲解,我们已经知道如何将文本数据和二进制数据保存到文件中,那么这里还有一个问题,如果希望把一个列表或者一个字典中的数据保存到文件中又该怎么做呢?答案是将数据以JSON格式进行保存。JSON是“JavaScript Object Notation”的缩写,它本来是JavaScript语言中创建对象的一种字面量语法,现在已经被广泛的应用于跨平台跨语言的数据交换,原因很简单,因为JSON也是纯文本,任何系统任何编程语言处理纯文本都是没有问题的。目前JSON基本上已经取代了XML作为异构系统间交换数据的事实标准。关于JSON的知识,更多的可以参考JSON的官方网站,从这个网站也可以了解到每种语言处理JSON数据格式可以使用的工具或三方库,下面是一个JSON的简单例子。

{
    'name': '骆昊',
    'age': 38,
    'qq': 957658,
    'friends': ['王大锤', '白元芳'],
    'cars': [
        {'brand': 'BYD', 'max_speed': 180},
        {'brand': 'Audi', 'max_speed': 280},
        {'brand': 'Benz', 'max_speed': 320}
    ]
}

可能大家已经注意到了,上面的JSON跟Python中的字典其实是一样一样的,事实上JSON的数据类型和Python的数据类型是很容易找到对应关系的,如下面两张表所示。

JSONPython
objectdict
arraylist
stringstr
number (int / real)int / float
true / falseTrue / False
nullNone
PythonJSON
dictobject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumber
True / Falsetrue / false
Nonenull

我们使用Python中的json模块就可以将字典或列表以JSON格式保存到文件中,代码如下所示。

import json


def main():
    mydict = {
        'name': '骆昊',
        'age': 38,
        'qq': 957658,
        'friends': ['王大锤', '白元芳'],
        'cars': [
            {'brand': 'BYD', 'max_speed': 180},
            {'brand': 'Audi', 'max_speed': 280},
            {'brand': 'Benz', 'max_speed': 320}
        ]
    }
    try:
        with open('data.json', 'w', encoding='utf-8') as fs:
            json.dump(mydict, fs)
    except IOError as e:
        print(e)
    print('保存数据完成!')


if __name__ == '__main__':
    main()

json模块主要有四个比较重要的函数,分别是:

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

这里出现了两个概念,一个叫序列化,一个叫反序列化。自由的百科全书维基百科上对这两个概念是这样解释的:“序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换为可以存储或传输的形式,这样在需要的时候能够恢复到原先的状态,而且通过序列化的数据重新获取字节时,可以利用这些字节来产生原始对象的副本(拷贝)。与这个过程相反的动作,即从一系列字节中提取数据结构的操作,就是反序列化(deserialization)”。

目前绝大多数网络数据服务(或称之为网络API)都是基于HTTP协议提供JSON格式的数据,关于HTTP协议的相关知识,可以看看阮一峰老师的《HTTP协议入门》,如果想了解国内的网络数据服务,可以看看聚合数据和阿凡达数据等网站,国外的可以看看{API}Search网站。下面的例子演示了如何使用requests模块(封装得足够好的第三方网络访问模块)访问网络API获取国内新闻,如何通过json模块解析JSON数据并显示新闻标题,这个例子使用了天行数据提供的国内新闻数据接口,其中的APIKey需要自己到该网站申请。

import requests
import json


def main():
    resp = requests.get('http://api.tianapi.com/guonei/?key=APIKey&num=10')
    data_model = json.loads(resp.text)
    for news in data_model['newslist']:
        print(news['title'])


if __name__ == '__main__':
    main()

在Python中要实现序列化和反序列化除了使用json模块之外,还可以使用pickle和shelve模块,但是这两个模块是使用特有的序列化协议来序列化数据,因此序列化后的数据只能被Python识别。关于这两个模块的相关知识可以自己看看网络上的资料。另外,如果要了解更多的关于Python异常机制的知识,可以看看segmentfault上面的文章《总结:Python中的异常处理》,这篇文章不仅介绍了Python中异常机制的使用,还总结了一系列的最佳实践,很值得一读。

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

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

相关文章

重温被Mamba带火的SSM:HiPPO的一些遗留问题

©PaperWeekly 原创 作者 | 苏剑林 单位 | 科学空间 研究方向 | NLP、神经网络 书接上文&#xff0c;在上一篇文章《重温被Mamba带火的SSM&#xff1a;线性系统和HiPPO矩阵》中&#xff0c;我们详细讨论了 HiPPO 逼近框架其 HiPPO 矩阵的推导&#xff0c;其原理是通过正交…

MySQL的Geometry数据处理之WKB方案

MySQL的Geometry数据处理之WKT方案&#xff1a;https://blog.csdn.net/qq_42402854/article/details/140134357 MySQL的Geometry数据处理之WKT方案中&#xff0c;介绍WTK方案的优点&#xff0c;也感受到它的繁琐和缺陷。比如&#xff1a; 需要借助 ST_GeomFromText和 ST_AsTex…

Gradio 教程四:Building Generative AI Applications with Gradio

文章目录 一、使用interface构建NLP应用1.1 构建文本摘要应用1.1.1 设置API密钥1.1.2 调用文本摘要API1.1.3 运行本地模型获取响应1.1.4 使用interface构建应用 1.2 构建命名实体识别应用1.2.1 调用NER任务API1.2.2 使用interface构建应用1.2.3 加入额外函数&#xff0c;合并to…

C语言实战 | 用户管理系统

近期推出的青少年防沉迷系统&#xff0c;采用统一运行模式和功能标准。在“青少年模式”下&#xff0c;未成年人的上网时段、时长、功能和浏览内容等方面都有明确的规范。防沉迷系统为青少年打开可控的网络空间。 01、综合案例 防沉迷系统的基础是需要一个用户管理系统管理用户…

Unity3d C#实现基于UGUI ScrollRect的轮播图效果功能(含源码)

前言 轮播功能是一种常见的页面组件&#xff0c;用于在页面中显示多张图片/素材并自动或手动进行切换&#xff0c;以提高页面的美观度和用户体验。主要的功能是&#xff1a;自动/手动切换;平滑的切换效果;导航指示器等。可惜Unity的UGUI系统里没有现成的实现该功能&#xff0c…

[Labview] 改写表格内容并储存覆盖Excel

在上一个功能的基础上&#xff0c;新增表格改写保存功能 [Labview] Excel读表 & 输出表单中选中的单元格内容https://blog.csdn.net/Katrina419/article/details/140120584 Excel修改前&#xff1a; 修改保存后&#xff0c;动态改写储存Excel&#xff0c;并重新写入新的表…

使用antd的<Form/>组件获取富文本编辑器输入的数据

前端开发中&#xff0c;嵌入富文本编辑器时&#xff0c;可以通过富文本编辑器自身的事件处理函数将数据传输给后端。有时候&#xff0c;场景稍微复杂点&#xff0c;比如一个输入页面除了要保存富文本编辑器的内容到后端&#xff0c;可能还有一些其他输入组件获取到的数据也一并…

Go - 8.func 函数使用

目录 一.引言 二.func 定义 三.func 实践 1.多个返回值 2.命名返回值 3.可变参数 四.总结 一.引言 函数是编程语言中的基本构建块&#xff0c;用于将代码组织成可重用的逻辑单元。函数可以接受输入参数&#xff0c;执行特定的操作&#xff0c;并返回结果。在 Go 语言&a…

设计IC行业SAP软件如何处理芯片成本计算

在集成电路(IC)设计与制造行业中&#xff0c;精确的成本计算对于维持健康的财务状况、优化生产流程以及保持市场竞争力至关重要。SAP软件&#xff0c;作为一种全面的企业资源规划(ERP)解决方案&#xff0c;为IC行业提供了强大且灵活的成本计算工具。以下是SAP软件如何处理芯片成…

【python】OpenCV—Feature Detection and Matching

参考学习来自OpenCV基础&#xff08;23&#xff09;特征检测与匹配 文章目录 1 背景介绍2 Harris角点检测3 Shi-Tomasi角点检测4 Fast 角点检测5 BRIEF 特征描述子6 ORB(Oriented Fast and Rotated Brief) 特征描述子7 SIFT(Scale Invariant Feature Transform) 特征描述子8 SU…

​​​​​​​​​​​​​​Spark Standalone集群环境

目录 Spark Standalone集群环境 修改配置文件 【workers】 【spark-env.sh】 【配置spark应用日志】 【log4j.properties】 分发到其他机器 启动spark Standalone 启动方式1&#xff1a;集群启动和停止 启动方式2&#xff1a;单独启动和停止 连接集群 【spark-shel…

基于Hadoop平台的电信客服数据的处理与分析③项目开发:搭建基于Hadoop的全分布式集群---任务1:运行环境说明

任务描述 项目的运行环境是基于Hadoop的全分布式模式集群。 任务的主要内容是规划集群节点及网络使用&#xff0c;准备初始环境&#xff0c;关闭防火墙和Selinux。 任务指导 1. 基于Hadoop的全分布式模式集群&#xff0c;如下图所示&#xff1b; 2. 硬软件环境&#xff1a;…

Android性能优化面试题经典之ANR的分析和优化

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 造成ANR的条件 以下四个条件都可以造成ANR发生&#xff1a; InputDispatching Timeout&#xff1a;5秒内无法响应屏幕触摸事件或键盘输入事件 …

《企业实战分享 · MyBatis 使用合集》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

Seatunnel本地模式快速测验

前言 SeaTunnel&#xff08;先前称为WaterDrop&#xff09;是一个分布式、高性能、易于扩展的数据集成平台&#xff0c;旨在实现海量数据的同步和转换。它支持多种数据处理引擎&#xff0c;包括Apache Spark和Apache Flink&#xff0c;并在某个版本中引入了自主研发的Zeta引擎…

虚拟机交叉编译基于ARM平台的opencv(ffmpeg/x264)

背景&#xff1a; 由于手上有一块rk3568的开发板&#xff0c;需要运行yolov5跑深度学习模型&#xff0c;但是原有的opencv不能对x264格式的视频进行解码&#xff0c;这里就需要将ffmpegx264编译进opencv。 但是开发板算力有限&#xff0c;所以这里采用在windows下&#xff0c;安…

2024年07年01日 Redis数据类型以及使用场景

String Hash List Set Sorted Set String&#xff0c;用的最多&#xff0c;对象序列化成json然后存储 1.对象缓存&#xff0c;单值缓存 2.分布式锁 Hash&#xff0c;不怎么用到 1.可缓存经常需要修改值的对象&#xff0c;可单独对对象某个属性进行修改 HMSET user {userI…

Element中的选择器组件Select (一级选择组件el-select)

简述&#xff1a;在 Element UI 中&#xff0c;ElSelect&#xff08;或简称为 Select&#xff09;是一个非常常用的选择器组件&#xff0c;它提供了丰富的功能来帮助用户从一组预定义的选项中选择一个或多个值。这里来简单记录一下 一. 组件和属性配置 <el-selectv-model&q…

经典FC游戏web模拟器--EmulatorJS

简介 EmulatorJS是一个基于JavaScript和Webassembly技术的虚拟环境的实现&#xff0c;可以在网页中运行各种经典FC游戏系统&#xff0c;支持任天堂、世嘉、雅达利等经典红白机。EmulatorJS的诞生使得诸如超级玛丽、坦克大战、魂斗罗等经典FC游戏能够以一种全新的方式回归。本文…

MySQL:高效的索引

数据库索引 1. 索引介绍1.1 创建索引1.2 查看索引 2. 索引应用2.1 前缀索引2.2 全文索引2.3 复合索引2.4 复合索引中的列顺序2.5 建立最佳索引2.6 使用索引排序2.7 覆盖索引 3. 维护索引4. 建立性能数据库 索引对大型和高并发数据库非常有用&#xff0c;因为它可以显著提升查询…