【Python 1-17】Python手把手教程之——文件的读写以及I/O操作

2023-11-18

作者 | 弗拉德
来源 | 弗拉德(公众号:fulade_me)

从文件中读取数据

文本文件可存储的数据量很多,每当需要分析或修改存储在文件中的信息时,读取文件都很有用,对数据分析应用程序来说尤其 如此。例如,你可以编写一个这样的程序:读取一个文本文件的内容,重新设置这些数据的格式 并将其写入文件,让浏览器能够显示这些内容。
要使用文本文件中的信息,首先需要将信息读取到内存中。为此,你可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。

读取整个文件

要读取文件,需要一个包含几行文本的文件。下面首先来创建一个文件,它包含精确到小数点后30位的圆周率值,且在小数点后每10位处都换行:

3.1415926535 
8979323846 
2643383279

我们把它保存为pi_digits.txt文件

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

我们先来看看函数open()。要以任何方式使用文件——哪怕仅仅是打印其内容,都得先打开文件,这样才能访问它。函数open()接受一个参数: 要打开的文件的名称。Python在当前执行的文件所在的目录中查找指定的文件。在这个示例中,假如我们把文件保存为file_reader.py,因此Python在file_reader.py所在的目录中查找pi_digits.txt。函数open()返回一个表示文件的对象。在这里,open('pi_digits.txt')返回一个表示文件pi_digits.txt的对象,Python将这个对象存储在我们将在后面使用的变量中。
关键字with在不再需要访问文件后将其关闭。在这个程序中,注意到我们调用了open(),但没有调用close(),你也可以调用open()close()来打开和关闭文件,但这样做时,如果程序存在bug,导致close()语句未执行,文件将不会关闭。这看似微不足道,但未妥善地关闭文件可能会导致数据丢失或受损。如果在程序中过早地调用close(),你会发现需要使用文件时它已关闭,这会导致更多的错误。并非在任何情况下都能轻松确定关闭文件的恰当时机,但通过使用前面所示的结构,可让Python去确定:你只管打开文件,并在需要时使用它,Python自会在合适的时候自动将其关闭。
通过打印contents的值,就可将这个文本文件的全部内容显示出来:

3.1415926535 
8979323846 
2643383279

文件路径

当你将类似pi_digits.txt这样的简单文件名传递给函数open()时,Python将在当前执行的文件所在的目录中查找文件。
根据你组织文件的方式,有时可能要打开不在程序文件所属目录中的文件。例如,你可能将 程序文件存储在了文件夹python_work中,而在文件夹python_work中,有一个名为text_files的文件夹,用于存储程序文件操作的文本文件。虽然文件夹text_files包含在文件夹python_work中,但仅向open()传递位于该文件夹中的文件的名称也不可行,因为Python只在文件夹python_work中查找,而不会在其子文件夹text_files中查找。要让Python打开不与程序文件位于同一个目录中的文件,需要提供文件路径,它让Python到系统的特定位置去查找。
由于文件夹text_files位于文件夹python_work中,因此可使用相对文件路径来打开该文件夹中的文件。相对文件路径让Python到指定的位置去查找,而该位置是相对于当前运行的程序所在目录的。在Linux和OS X中,你可以这样编写代码:

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

这行代码让Python到文件夹python_work下的文件夹text_files中去查找指定的.txt文件。在Windows系统中,在文件路径中使用反斜杠\而不是斜杠/:

with open('text_files\filename.txt') as file_object:

你还可以将文件在计算机中的准确位置告诉Python,这样就不用关心当前运行的程序存储在什么地方了。这称为绝对文件路径。在相对路径行不通时,可使用绝对路径。例如,如果text_files并不在文件夹python_work中,而在文件夹other_files中,则向open()传递路径'text_files/ filename.txt'行不通,因为Python只在文件夹python_work中查找该位置。为明确地指出你希望Python到哪里去查找,你需要提供完整的路径。
绝对路径通常比相对路径更长,因此将其存储在一个变量中,再将该变量传递给open()会有所帮助。在Linux和OS X中,绝对路径类似于下面这样:

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

而在Windows系统中,它们类似于下面这样:

file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:

通过使用绝对路径,可读取系统任何地方的文件。就目前而言,最简单的做法是,要么将 据文件存储在程序文件所在的目录,要么将其存储在程序文件所在目录下的一个文件夹(如text_files)中。

逐行读取

读取文件时,常常需要检查其中的每一行:你可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。例如,你可能要遍历一个包含天气数据的文件,并使用天气描述中包含字样sunny的行。在新闻报道中,你可能会查找包含标签<headline>的行,并按特定的格式设置它。
要以每次一行的方式检查文件,可对文件对象使用for循环:

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

我们将要读取的文件的名称存储在变量filename中,这是使用文件时一种常见的做法。由于变量filename表示的并非实际文件——它只是一个让Python知道到哪里去查找文件的字符串,因此可轻松地将’pi_digits.txt’替换为你要使用的另一个文件的名称。

调用open()后,将一个表示文件及其内容的对象存储到了变量file_object中。这里也使用了关键字with,让Python负责妥善地打开和关闭文件。为查看文件的内容,我们通过对文件对象执行循环来遍历文件中的每一行,我们打印每一行时,发现空白行更多了:

3.1415926535 

8979323846

2643383279

为何会出现这些空白行呢?因为在这个文件中,每行的末尾都有一个看不见的换行符,而print语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自print语句。

创建一个包含文件各行内容的列表

使用关键字with时,open()返回的文件对象只在with代码块内可用。如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表:你可以立即处理文件的各个部分,也可推迟到程序后面再处理。
下面的示例在with代码块中将文件pi_digits.txt的各行存储在一个列表中,再在with代码块外打印它们:

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

我们先使用方法readlines()从文件中读取每一行,并将其存储在一个列表中接下来,该列表被存储到变量lines中;在with代码块外,我们依然可以使用这个变量。我们使用一个简单的for循环来打印lines中的各行。由于列表lines的每个元素都对应于文件中的一行,因此输出 与文件内容完全一致。

使用文件的内容

将文件读取到内存中后,就可以以任何方式使用这些数据了。下面以简单的方式使用圆周率 的值。首先,我们将创建一个字符串,它包含文件中存储的所有数字,且没有任何空格:


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))

就像前一个示例一样,我们首先打开文件,并将其中的所有行都存储在一个列表中。我们创建了一个变量——pi_string,用于存储圆周率的值。接下来,我们使用一个循环将各行都加入pi_string,并删除每行末尾的换行符。接着,我们打印这个字符串及其长度:

3.1415926535 8979323846 2643383279
36

在变量pi_string存储的字符串中,包含原来位于每行左边的空格,为删除这些空格,可使用strip()而不是rstrip():

filename = 'pi_30_digits.txt'
with open(filename) as file_object: 
    lines = file_object.readlines()
pi_string = ''
for line in lines:
    pi_string += line.strip()
print(pi_string) 
print(len(pi_string))

这样,我们就获得了一个这样的字符串:它包含精确到30位小数的圆周率值。这个字符串长32字符,因为它还包含整数部分的3和小数点:

3.141592653589793238462643383279
36

写入文件

保存数据的最简单的方式之一是将其写入到文件中。通过将输出写入文件,即便关闭包含程 序输出的终端窗口,这些输出也依然存在:你可以在程序结束运行后查看这些输出,可与别人分享输出文件,还可编写程序来将这些输出读取到内存中并进行处理。

写入空文件

要将文本写入文件,你在调用open()时需要提供另一个实参,告诉Python你要写入打开的文 件。为明白其中的工作原理,我们来将一条简单的消息存储到文件中,而不是将其打印到屏幕上:

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

在这个示例中,调用open()时提供了两个实参。第一个实参也是要打开的文件的名称; 第二个实参w告诉Python,我们要以写入模式打开这个文件。打开文件时,可指定读取模式r、写入模式w、附加模式a或让你能够读取和写入文件的模式r+。如果 你省略了模式实参,Python将以默认的只读模式打开文件。

如果你要写入的文件不存在,函数open()将自动创建它。然而,以写入w模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件。
我们使用文件对象的方法write()将一个字符串写入文件。这个程序没有终端输出,但如果你打开文件programming.txt,将看到其中包含如下一行内容:

I love programming.

相比于你的计算机中的其他文件,这个文件没有什么不同。你可以打开它、在其中输入新文本、复制其内容、将内容粘贴到其中等。

写入多行

函数write()不会在你写入的文本末尾添加换行符,因此如果你写入多行时没有指定换行符,
文件看起来可能不是你希望的那样:

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

如果你打开programming.txt,将发现两行内容挤在一起:

I love programming.I love creating new games.

要让每个字符串都单独占一行,需要在write()语句中包含换行符:

filename = 'programming.txt'
with open(filename, '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.

追加写入文件

如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式打开文件。你以附加模式打开文件时,Python不会在返回文件对象前清空文件,而你写入到文件的行都将添加到文件末尾。如果指定的文件不存在,Python将为你创建一个空文件。

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

我们打开文件时指定了实参a,以便将内容附加到文件末尾,而不是覆盖文件原来的内容。然后,我们又写入了两行,它们被添加到文件programming.txt末尾:

I love programming.
I love creating new games.
I also love finding meaning in large datasets.
I love creating apps that can run in a browser.

最终的结果是,文件原来的内容还在,它们后面是我们刚添加的内容。 19

小作业
17-1 在文本编辑器中新建一个文件,写几句话来总结一下你至
此学到的Python知识。将这个文件命名为 learning_python.txt,并将其存储到为完成本章练习而编写的程序所在的目录中。编写一个程序,读取整个文件,并打印。
17-2 访客:编写一个程序,提示用户输入其名字;用户作出响应后,将其名字写入到文件 guest.txt中。

想查看作业答案可以去我的Githu仓库在文件夹17-1_17-2


公众号

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Python 1-17】Python手把手教程之——文件的读写以及I/O操作 的相关文章

随机推荐

  • 1.R语言基础知识

    目录 一 R语言的介绍 R语言的下载与按照 Rstudio R包的安装 工作空间管理 基本运算 二 R的数据结构 1 数据类型 2 数据类型的转换和判断 3 数据结构 三 导入 导出数据 获取内置数据集 获取其他格式的数据 四 数据框的常用
  • AI绘画指南:在CentOS7中安装Stable Diffusion WebUI

    一 安装GPU驱动 1 1 购买云服务器 在腾讯云选购一台GPU型的服务器 最好的境外的 境外的服务器后面关于镜像加速的步骤都可以跳过 购买成功之后腾讯的站内信会发送初始的密码给你 登录成功后会自动帮我们安装相关的驱动 提示整个过程大概需要
  • LeetCode-283. 移动零【数组,双指针】

    LeetCode 283 移动零 数组 双指针 题目描述 解题思路一 首先想到的是双指针 但是不行 非零元素的位置会改变 解题思路二 改进的是每次从当前0元素的位置取后面第一个非0元素替换过来 替换之和那个break非常重要 解题思路三 优
  • Future 和 Callable

    一 Runnable 缺陷 不能返回一个返回值 不能抛出 checked Execption 二 Callable接口 类似于Runnable 被其他线程执行的任务 实现call方法 有返回值 三 Future的作用 Callable和Fu
  • 【infiniband】 MAD、 uMAD、Verbs、RDMACM

    1 MAD Management Datagram MAD是InfiniBand网络中用于管理和配置的数据报文 它包含了各种类型的管理操作 如查询端口状态 配置端口参数等 MAD通常用于执行网络管理任务 2 uMAD User MAD uM
  • 模板类 通用数组的实现

    实现自定义数组 重载 lt lt 运算符 并且数组可以使用自定义类 头文件 ifndef MYARRAY H define MYARRAY H include
  • pandas datetime与时间戳互相转换,字符串转换datetime

    参考pandas to datetime的api 字符串转换为pandas datetime 通过to datetime函数可以把字符串转换为pandas datetime df pd DataFrame date 2011 04 24 0
  • python的xlrd、xlwt模块/pymsql使用

    xlrd模块 https www cnblogs com machangwei 8 p 10736528 html label0 xlwt模块https www cnblogs com machangwei 8 p 10738244 htm
  • Filter过滤器实现权限拦截

    一 要求 用户登陆之后才能进入主页 用户注销之后不能进入首页 二 思路 用户登陆之后 向session中放入用户的数据 进入主页的时候要判断用户是否已经登陆 在过滤器中实现 public void doFilter ServletReque
  • 电脑怎样连接打印机?分享4个简单操作!

    为了更方便学习 我买了一个打印机来打印需要用的资料 但是操作了半天还是没连接上 想请问一下有经验的朋友是怎么将打印机与电脑进行连接的呢 在现代人的工作和生活中 打印机是一个重要的设备 我们可以利用打印机进行资料 文件等的打印 但是也会有很多
  • SpringBoot调用PageHelper.startPage(Object params)报错:分页查询缺少必要的参数:XXX

    问题描述 项目中使用了MyBatis分页插件 调用以下方法实现分页 无论传入JavaBean还是Map都报错 分页查询缺少必要的参数 XXX Map
  • 【Docker】云原生利用Docker确保环境安全、部署的安全性、安全问题的主要表现和新兴技术产生

    前言 Docker 是一个开源的应用容器引擎 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中 然后发布到任何流行的Linux或Windows操作系统的机器上 也可以实现虚拟化 容器是完全使用沙箱机制 相互之间不会有任何接口 云原生
  • Python学习 第二章 数据类型

    Python学习 第二章 数据类型上 1 数字 1 1 整型 int 1 2 浮点型 float 1 3 布尔类型 bool 1 4 代码实现 1 5 复数 2 字符串 string 2 1 如果字符串内容中出现了引号 2 2 代码实现 2
  • pandas生成excel文件

    可以使用pandas中的to excel 函数将DataFrame数据写入Excel文件 例如 import pandas as pd 创建测试数据 data name Mike John Bob age 25 32 45 city New
  • STM-32:SPI通信协议/W25Q64简介—软件SPI读写W25Q64

    目录 一 SPI简介 1 1电路模式 1 2通信原理 1 3SPI时序基本单元 1 3 1起始和终止 1 3 2交换字节 二 W25Q64 2 1W25Q64简介 2 2W25Q64硬件电路 2 3W25Q64框图 2 4Flash操作注意
  • double类型精度丢失问题以及解决方法

    double类型精度丢失问题 1 加法运算 public static void main String args double number1 1 double number2 20 2 double number3 300 03 dou
  • arcgis for android 学习 - (5) 在地图指定位置添加“标记“,并尝试选中它

    我做一个例子 1 首先显示一个地图 2 点击 添加要素 按钮后再次点击地图 将会在地图上添加 红色的位置标记 3 再次点击按钮后 这时 就可以点击刚刚添加的 红色的位置标记 就可以查看到 该标记关联到得属性值 布局
  • NO.17 浅谈共识机制(POW、POS、DPOS、PBFT、POP)

    区块链是一种去中心化的分布式账本 可以简单理解为分布在全球各个节点的分布式数据库 数据库由区块按时间顺序相连而成 区块中记录的是数笔交易 为了能支持这一套系统的运行 需要各节点矿工的参与 他们参与的主要原因是因为有奖励 奖励可以去交易所换成
  • kafka消费者客户端线程安全以及多线程实现并发读取消息

    kafka的生产者客户端Producer是线程安全的 但是消费者客户端是非线程安全的 每次操作时都会调用accqure方法用来确定当前只有一个线程操作 如果有多个线程在操作 会抛出CME异常 针对这种情况 为了能够多线程更快速的读取消息 可
  • 【Python 1-17】Python手把手教程之——文件的读写以及I/O操作

    作者 弗拉德 来源 弗拉德 公众号 fulade me 从文件中读取数据 文本文件可存储的数据量很多 每当需要分析或修改存储在文件中的信息时 读取文件都很有用 对数据分析应用程序来说尤其 如此 例如 你可以编写一个这样的程序 读取一个文本文