python-基础篇-文件和异常

文章目录

    • 文件和异常
      • 读写文本文件
      • 读写二进制文件
      • 读写JSON文件

文件和异常

实际开发中常常会遇到对数据进行持久化操作的场景,而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词,可能需要先科普一下关于文件系统的知识,但是这里我们并不浪费笔墨介绍这个概念,请大家自行通过维基百科进行了解。

在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.mfbz.cn/a/710344.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Chromium源码阅读:从页面加载到元素展示(1)

​ 从&#xff1c;p&#xff1e;hello world&#xff1c;/p&#xff1e;.html到界面上的hello world 今天&#xff0c;我们一起来看看一个html元素&#xff0c;是如何绘制到界面上。我们选择了最简单的场景&#xff0c;便于快速掌握总体的流程&#xff0c;加深之前阅读知识的…

深入理解并打败C语言难关之一————指针(4)

前言&#xff1a; 我们在前面的几讲中已经讲了指针的很多内容了&#xff0c;现在我们开始层层递进&#xff0c;要探寻更多的指针喽&#xff0c;不多废话了&#xff0c;直接进入正题&#xff0c;开始今天的指针之旅喽&#xff01; 目录&#xff1a; 1.字符指针变量 1.1常量字符…

除了程序员,你又是谁呢?别说!保护自己能量最好的方式——早读(逆天打工人爬取热门微信文章解读)

你很困的时候&#xff0c;会不会遵循本心直接睡觉呢&#xff1f; 引言Python 代码第一篇 洞见 保护自己能量最好的方式第二篇 视频新闻结尾 引言 现在真的是越来越遵循本心了 昨天晚上10点多 觉得好困 但是又没有洗澡 然后就想着算了 躺一个 没想到一躺 早上6点了 起来速速洗刷…

2024年心理学研究、现代化教育与社会发展国际学术会议(PRMESD 2024)

2024年心理学研究、现代化教育与社会发展国际学术会议(PRMESD 2024) 2024 International Conference on Psychological Research, Modern Education and Social Development 会议地点&#xff1a;南京&#xff0c;中国 网址&#xff1a;www.prmesd.com 邮箱: prmesdsub-con…

浔川计算机v1.1——浔川python科技社

浔川计算机v1.1 import tkinter import math import tkinter.messageboxclass Calculator(object):# 界面布局方法def __init__(self):# 创建主界面,并且保存到成员属性中self.root tkinter.Tk()self.root.minsize(280, 450)self.root.maxsize(280, 470)self.root.title(浔川计…

LabVIEW 32位与64位版本比较分析:性能与兼容性详解

LabVIEW的32位和64位版本在功能、性能、兼容性和应用场景等方面存在差异。本文从系统要求、内存管理、性能、兼容性、驱动支持和开发维护等多个角度进行详细分析&#xff0c;帮助用户选择合适的版本。 一、系统要求 操作系统支持&#xff1a; 32位LabVIEW&#xff1a;可以在32位…

vue+elementUI实现在表格中添加输入框并校验的功能

背景&#xff1a; vue2elmui 需求&#xff1a; 需要在一个table中添加若干个输入框&#xff0c;并且在提交时需要添加校验 思路&#xff1a; 当需要校验的时候可以考虑添加form表单来触发校验&#xff0c;因此需要在table外面套一层form表单&#xff0c;表单的属性就是ref…

ComfyUI 宝藏插件之辅助工具

今天我们就来分享下这个 ComfyUI 辅助脚本工具的功能。 插件安装&#xff0c;小伙伴们直接在管理器里搜索「ComfyUI-Custom-Scripts」&#xff0c;点击安装就可以了&#xff0c;这里再告诉小伙伴们一个小技巧&#xff0c;点击名称可以跳转到插件所在的官网哦。 没有安装管理器…

Tdengine的时序数据库简介、单机部署、操作语句及java应用

Tdengine的时序数据库简介、单机部署、操作语句及java应用 本文介绍了Tdengine的功能特点、应用场景、超级表和子表等概念&#xff0c;讲述了Tdengine2.6.0.34的单机部署&#xff0c;并介绍了taos数据库的常见使用方法及特色窗口查询方法&#xff0c;最后介绍了在java中的应用。…

AI助力密码安全:利用机器学习提升密码安全性

信息安全已经成为了当今数字世界的一个核心问题&#xff0c;随着互联网技术使用场景的不断增加&#xff0c;创建和管理安全的密码已经成为了保证在线账户安全的关键要求。本文将研究和探讨如何利用人工智能&#xff08;AI&#xff09;和机器学习技术来提升密码的安全性。 学习目…

xgo 原理探索

Go 单测 mock 方案 Mock 方法原理依赖优点缺点接口 Mock为依赖项定义接口&#xff0c;并提供接口的 Mock 实现。需要定义接口和 Mock 实现。灵活&#xff0c;遵循 Go 的类型系统&#xff1b;易于替换实现。需要更多的样板代码来定义接口和 Mock 实现。Monkey Patching&#xf…

深度学习网络结构之---Inception

目录 一、Inception名称的由来 二、Inception结构 三、Inception v2 四、Inception v3 1、深度网络的通用设计原则 2.卷积分解&#xff08;Factorizing Convolutions&#xff09; 3.对称卷积分解 3.非对称卷积分解 五、Inception v4 一、Inception名称的由来 Inception网…

推荐一款好用的读论文软件操作方法

步骤&#xff1a; 1. 使用一译 —— 文档和论文翻译、对照阅读、讨论和社区 2.上传自己想要翻译的论文即可。 示例 Planing论文双语翻译 1.1 Parting with Misconceptions about Learning-based Vehicle Motion Planning 中英文对照阅读 1.2 Rethinking Imitation-based Pl…

3.多层感知机

目录 1.感知机训练感知机XOR问题&#xff08;Minsky&Papert 1969&#xff09; AI的第一个寒冬总结 2.多层感知机(MLP)学习XOR单隐藏层&#xff08;全连接层&#xff09;激活函数&#xff1a;Sigmoid激活函数&#xff1a;Tanh激活函数&#xff1a;ReLu 最常用的 因为计算速度…

AMSR-MODIS 边界层水汽 L3 每日 1 度 x 1 度 V1、V2 版本数据集

AMSR-MODIS Boundary Layer Water Vapor L3 Daily 1 degree x 1 degree V1 (AMDBLWV) at GES DISC AMSR-MODIS Boundary Layer Water Vapor L3 Daily 1 degree x 1 degree V2 (AMDBLWV) at GES DISC 简介 该数据集可估算均匀云层下的海洋边界层水汽。AMSR-E 和 AMSR-2 的微波…

使用libcurl实现简单的HTTP访问

代码; #include <stdio.h> #include <stdlib.h> #include <curl/curl.h> // 包含libcurl库 FILE *fp; // 定义一个文件标识符 size_t write_data(void *ptr,size_t size,size_t nmemb,void *stream) { // 定义回调函数&#xff0c;用于将…

MGRS坐标

一 概述 MGRS坐标系统&#xff0c;即军事格网参考系统&#xff0c;是北约(NATO)军事组织使用的标准坐标系统。它基于UTM&#xff08;通用横向墨卡托&#xff09;系统&#xff0c;并将每个UTM区域进一步划分为100km100km的小方块。这些方块通过两个相连的字母标识&#xff0c;其…

华为云开发者社区活动-基于MindNLP的ChatGLM-6B聊天机器人体验

MindNLP ChatGLM-6B StreamChat 本案例基于MindNLP和ChatGLM-6B实现一个聊天应用。支持流式回复。 本活动通过配置环境&#xff0c;模型接入&#xff0c;以及gradio前端界面搭建&#xff0c;实现了聊天机器人的功能。 以下是一些体验记录&#xff1a; 有兴趣的可以通过以下链…

详细解析找不到msvcp120.dll文件的原因及解决方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到msvcp120.dll”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;给使用者带来了困扰。那么&#xff0c;究竟是什么原因导致了这个问题的出现&#xff1f;又该如何解决呢&a…

【每日刷题】Day64

【每日刷题】Day64 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCP 67. 装饰树 - 力扣&#xff08;LeetCode&#xff09; 3. 1315. 祖父节点值为偶数的节点和 - 力…