0
点赞
收藏
分享

微信扫一扫

网工速通Python-part7-文本文件的操作

前言:

《从零开始NetDevOps》是本人8年多的NetDevOps实战总结的一本书(且称之为书,通过公众号连载的方式,集结成册,希望有天能以实体书的方式和大家相见)。

NetDevOps是指以网络工程师为主体,针对网络运维场景进行自动化开发的工作思路与模式,是2014年左右从国外刮起来的一股“网工学Python"的风潮,最近几年在国内逐渐兴起。本人在国内某大型金融机构的数据中心从事网络自动化开发8年之久,希望能通过自己的知识分享,给大家呈现出一个不同于其他人的实战为指导、普适性强、善于抠细节、知其然知其所以然风格、深入浅出的NetDevOps知识体系,给大家一个不同的视角,一个来自于实战中的视角。

由于时间比较仓促,文章中难免有所纰漏,敬请谅解,同时笔者也会在每个章节完成后进行修订再发布,欢迎大家持续关注

2.8 文本文件的操作

网络日常运维对纯文本的相关处理是十分常见的操作,纯文本可以简单理解为记事本类应用可以打开并显示出来字符串的文档,包括Python代码纯从编辑的角度来看也是一个纯文本文件。这些文件有别于Excel表格、Word文档、PNG图片等有特殊数据结构和格式的文件,它们需要特殊的软件才能打开。

Python也提供了非常便利的函数,让我们可以访问文件(纯文本类和复杂类),其方式是通过open函数,我们本节只讨论纯文本文件,对其操作也聚焦在字符串层面的相关内容。

关于open函数的参数说明如下:

open(name=<文件名>,mode=<读写模式>,encoding=<字符集>)

  1. name是文件名,我们直接要操作的文件的相对路径或者绝对路径,含文件名,建议新手将代码和文本文件都在工程根目录下,不要有任何层级,直接用文件名即可,如使用绝对路径,反斜杠一定使用转义后的\\,如"C:\\netdevops.txt"是正确的,而"C:\netdevops.txt"是错误的。或者在字符串外面加一个r取消转义r"C:\netdevops.txt",这个r的意思是取消转义,反斜杠只代表自己本身的字符,不再代表转义符。
  2. mode是对文件操作的模式,对于初学者,我们只需记住三种rwa,即读、写、追加(可以理解为写的一种特殊模式),对应单词read、write与append,方便记忆。读模式文件不存在,代码会报错。写模式与追加模式,如果文件不存在,Python会自动创建一个文件。如文件存在,写模式会覆盖,而追加模式会在文本后追加我们写要入的内容。
  3. encoding是字符集一定要显式地指定utf8,Python非常灵活,各种形式的字符集书写形式(大小写短横线等,如utf8、UTF8、UTF-8)它都会自动识别出。

在使用这个函数之前,我们先定几个重要的结论,再来看代码,可以有效避坑:

  1. 在我们自己编写的代码体系里一定要用utf8字符集
  2. 读取别人的文本的时候选择utf8字符集另存为一个新文件供程序使用,后续讨论不再赘述其他字符集
  3. 一定要用上下文管理关键字with来打开文件对象
  4. 一定要显式的赋值读写的模式以及字符集名称

2.8.1 文本的读取

对文件操作我们使用open函数创建一个文件对象,实际上是一个句柄指向了操作系统的文件对象,我们执行read方法,可以对文本文件进行读取内容的操作,返回一个字符串。在操作完成后,我们需要关闭文件句柄(调用文件对象的close方法),以防止读写冲突之类的事情放生。

示例代码:

首先我们创建一个文本netdevops.txt,内容如下:

this is a book about “NetDevOps”!
这是一本关于NetDevOps的书!

代码部分如下:

# 我们用IDE创建一个文件,叫做netdevops.txt,编码采用utf8字符集
f = open('netdevops.txt', mode='r', encoding='utf8')
print(f, type(f))
# 上述会输出<_io.TextIOWrapper name='netdevops.txt' mode='r' encoding='utf8'> <class '_io.TextIOWrapper'>
content = f.read()
print(content)  # 输出我们文件的内容,字符串
f.close()  # 关闭文件对象

但是这个过程显得比较麻烦,因为我们每次要显式地关闭,这段代码没问题,但是不够pythonic,不够优雅,所以我们使用with来实现更加pythonic的代码。

with open('netdevops.txt', mode='r', encoding='utf8') as f:
    content = f.read()
    print(content)  # 输出我们文件的内容,字符串

with后面接open函数,使用as 关键字将文件对象赋值给f,然后是一个冒号,后面与判断循环格式一样,需要缩进控制代码块,当代码离开了with管辖的代码块,Python会自动执行对象的close方法(实际执行了对象内部的一个特殊的方法,我们此时不必深究)。如果我们读取一个已经关闭的文件,程序会报错,示例如下:

with open('netdevops.txt', mode='r', encoding='utf8') as f:
    content = f.read()
    print(content)  # 输出我们文件的内容,字符串

f.read() # 此处会报错,ValueError: I/O operation on closed file.

read方法会一次性读取文本的全部内容,返回一个字符串。如果我们按行处理的时候需要使用字符串的splitlines方法,它会自动帮我们切割成一行一行的字符串列表,然后我们可以结合之前所学,逐行去处理文本提取有用信息。这种一次性读取的方式日常使用没问题,但当文本文件非常大的时候,使用这种方法会出现内存溢出的风险,比如我们收集了防火墙很长一段时间的访问记录,可能是10多个G,如果使用read方法无法胜任。

遇到文本文件特别大的时候,我们可以使用for循环逐行读取内容,这也是一种非常pythonic的方法。

with open('netdevops.txt', mode='r', encoding='utf8') as f:
    for line in f:
        print(line)

这个输出结果是

this is a book about “NetDevOps”!

这是一本关于NetDevOps的书!

原因是每行的换行都保留了,实际不影响我们进行信息提取,大家知晓其原理即可:print函数会默认换行,for循环逐行读取文本,文本末尾的换行也保留。

如果在某些特殊情况下最后的换行符影响了我们的操作,我们可以通过字符串的操作,把最后的换行符取消。

文本的写入

open函数处理文本字符串写入的时候,只需要将模式mode按需赋值为w或者a,此处我们仅演示w模式即可,一定要注意字符集采用utf8,然后调用文件对象的write即可。

with open('netdevops_w.txt', mode='w', encoding='utf8') as f:
    content = '''this is a book about “NetDevOps”!
这是一本关于NetDevOps的书!'''
    f.write(content)

write方法负责将字符串写入到指定的文本文件中,若文本不存在则创建,若文件存在w模式会覆盖,a模式会追加。以上代码会创建一个netdevops_w.txt的文本文件。



举报

相关推荐

0 条评论