网络自动化运维 Help

1-2 本地文件读写和编码

后面章节的实验涉及到Python操作路由器系统,下载上传配置文件、批量运行路由器命令,因此需要复习本地文件读写。

后面章节涉及的telnet等早期协议比较偏底层,参数需要传输二进制 字节 。后面的协议如netconf发明较晚的协议更容易使用,传参时传递 字符串 ,第三方库会帮我们自动转字节, 因此需要理解 文本编码 (这部分书中第一章未详细解释)。

文本编码

引题:新建txt文件,输入'联想'保存,关闭文件后再打开发现字不见了。

1.最早时期 计算机发明时

想象一下你要在计算机上记录信息,发明了二极管、磁带、高低电平等物理设备、可表达2种状态,打算以二进制记录信息。 为了方便识别,规定8bit为1批即1byte字节,这样2的8次方有256种可能,足以表达26个英文字母的大小写和+-*/等常用符号。那么假设

a ➡️ 00000001 ➡️ 磁盘
b ➡️ 00000010
c ➡️ 00000011
...

顺着这个思路,恭喜,发明了从计算机诞生到现在每台电脑都一直使用的ASCII (American Standard Code for Information Interchange)编码。

1 2ascii

图片、视频的编解码暂时不讨论。

2.编码和解码定义

  • 编码: 字符串到二进制 a ➡️ 00000001。

  • 解码: 二进制到字符串 00000001 ➡️ a。
    语法str.encode()语法bytes.decode()这两个方法都有一个encoding参数,制定编解码时使用的字符集,一般为'utf-8',但Windows10老版本及以前为'gbk',因此建议显式指定。(稍后解释gbk和utf-8)

交互式解释器 中验证:

>>> 'a'.encode(encoding='ascii') b'a' >>> b'a'.decode(encoding='ascii') 'a'

疑问🤔,编码后的东西应该是二进制,根据ascii对照表,
'a' ➡️ 01100001
为什么结果为 b'a'?

其实结果就是二进制的01100001,但在编程语言中, 0 代表十进制的0, '0' 代表字符串。
必须有一个特殊语法符号代表二进制数字 ,因此需要表示为0b01100001
又因为二进制不方便识别,例如单词apple将会输出5串字节信息,因此Pycharm"贴心"地将能被ascii解码的二进制转为字符串'a',
但是此时还是想表示字节,因此添加前缀b (binary),最终显示为b'a'

你应该已经绕不过来了。现在,你只需要分清楚: 字符串'a',字节 b'a'

3.计算机传入各国时期 上世纪90年代 GBK编码

下一个问题,如果表示其它国家文字,常用的中文有2万多,加上生僻字后有6万多,1个字节256种可能显然不行。
那么就用2个字节,00000000 00000000,2的16次方=65536种可能。65536这个数字你可能在C语言和数据库中见过,思想都是如何把信息转换成物理信号。
假设,

'中' ➡️ 00000000 00000001
'国' ➡️ 00000000 00000010

恭喜,顺着这种思路,发明了中国GBK编码(国标扩展拼音首字母)。

>>>'中'.encode(encoding='gbk') b'\xd6\xd0' >>>b'\xd6\xd0'.decode(encoding='gbk') '中'

然而,产生了一些问题: 假设, '中' ➡️ 00000000 00000001
但是在日语Shift_JIS编码中 'の' ➡️ 00000000 00000001 在韩语...

这也是国外网页和软件产生乱码的原因,在代码中表现为报错

>>>'中'.encode(encoding='gbk') b'\xd6\xd0' >>> b'\xd6\xd0'.decode(encoding='ascii') Traceback (most recent call last): File "/Users/yangzheng/Applications/PyCharm Professional.app/Contents/plugins/python-ce/helpers/pydev/pydevconsole.py", line 364, in runcode coro = func() ^^^^^^ File "<input>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xd6 in position 0: ordinal not in range(128)
1 3

4.统一编码时期 2005年左右 UTF-8编码

为了避免各国自己一套规则,国际组织各国代表最终统一了全球文字编码, Unicode 通用编码(universal encode)。
采用4字节进行编码,2的32次方=4294967296,这是一个非常大的数字,足以把各国的语言文字都编进去,各国分配一个地址段,甚至还能编入emoji表情图,如果未来遇见外星人也能编入外星文字。

假设, '中' ➡️ 10100000 10000000 10000000 00000001

统一之后,唯一美中不足是,英文单字符用ascii占1字节,中文用gbk占用2字节,但用unicode的话占4字节,导致成本上升。 Unicode的解决方法是,在编码时向下兼容ascii编码,前三个字节有规律,亚洲文字一般用3个字节,emoji表情用4个字节。根据特殊的前缀规律和压缩算法, 英文字符可以压缩为1字节,中文可以压缩为3字节。虽然比gbk占用仍然多点,但是全球统一了,代价已经最小。

>>> '中'.encode(encoding='utf-8') b'\xe4\xb8\xad' >>> b'\xe4\xb8\xad'.decode(encoding='utf-8') '中' >>> b'a'.decode(encoding='utf-8') 'a'

这种经过压缩算法的Unicode实现,叫做 UTF-8 编码,也是现在90%以上网站和软件使用文本编码。

后面实验中注意

Python3已使用unicode编码处理程序中的字符串,不再需要 #-*- encoding:utf-8 -*- 文件头。
Pycharm默认unicode编码。
前几章的实验协议和相关库比较偏底层,传参需要传字节。后面的章节更自然,只使用字符串。 Linux/MacOS在很早已采用utf-8编码。Windows比较保守,Windows10 20h2(记不清了)的记事本是GBK编码,因此开发好的程序上传到服务器后可能乱码。

本地文件读写

写文本文件

# 用open方法打开文件句柄,第一个参数是文件路径,第二个参数是模式read读/write写/append追加,第三个编码用utf-8。w模式下文件不存在会自动创建。 file = open('./mytext.txt', mode='w', encoding='utf-8') # 写入字节流,write方法会自动把我们传入的字符串转换为字节。 file.write('hello world') file.write('你好') file.write('\n') file.write('小明') # 关闭文件防止资源泄漏 file.close()

观察文件是否生成,双击打开观察文件中的内容是否跟写入信息一样。

读文本文件

# 读取文本文件示例 file = open(file=r'D:\chinese_utf8.txt', mode='r', encoding='utf-8') content = file.read() print(content) file.close() """

with写法,虽然多了一层缩进,但操作文件的代码更独立,且会自动打开和关闭文件。

with open(file=r'D:\chinese_utf8.txt', mode='r', encoding='utf-8') as f: content = f.read() print(content)

其它练习,课本p10上面,把列表中的命令写入到一个txt文件中。

17 三月 2025