《Python Cookbook 3rd》笔记(5.16):增加或改变已打开文件的编码
增加或改变已打开文件的编码
问题
你想在不关闭一个已打开的文件前提下增加或改变它的 Unicode 编码。
解法
如果你想给一个以二进制模式打开的文件添加 Unicode 编码/解码方式,可以使用io.TextIOWrapper() 对象包装它。比如:
import urllib.request
import io
u = urllib.request.urlopen('http://www.python.org')
f = io.TextIOWrapper(u, encoding='utf-8')
text = f.read()
如果你想修改一个已经打开的文本模式的文件的编码方式,可以先使用 detach()方法移除掉已存在的文本编码层,并使用新的编码方式代替。下面是一个在sys.stdout 上修改编码方式的例子:
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='latin-1')
>>> sys.stdout.encoding
'latin-1'
>>>
这样做可能会中断你的终端,这里仅仅是为了演示而已。
PS. 我的测试结果
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> import io,sys
>>> sys.stdout.encoding
'utf-8'
>>> sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='latin-1')
Traceback (most recent call last):File "<pyshell#2>", line 1, in <module>sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='latin-1')
io.UnsupportedOperation: detach
>>>
讨论
I/O 系统由一系列的层次构建而成。你可以试着运行下面这个操作一个文本文件的例子来查看这种层次:
>>> f = open('sample.txt','w')
>>> f
<_io.TextIOWrapper name='sample.txt' mode='w' encoding='UTF-8'>
>>> f.buffer
<_io.BufferedWriter name='sample.txt'>
>>> f.buffer.raw
<_io.FileIO name='sample.txt' mode='wb'>
>>>
在这个例子中, io.TextIOWrapper 是一个编码和解码 Unicode 的文本处理层,io.BufferedWriter 是一个处理二进制数据的带缓冲的 I/O 层, io.FileIO 是一个表示操作系统底层文件描述符的原始文件。增加或改变文本编码会涉及增加或改变最上面的 io.TextIOWrapper 层。
一般来讲,像上面例子这样通过访问属性值来直接操作不同的层是很不安全的。例如,如果你试着使用下面这样的技术改变编码看看会发生什么:
>>> f
<_io.TextIOWrapper name='sample.txt' mode='w' encoding='UTF-8'>
>>> f = io.TextIOWrapper(f.buffer, encoding='latin-1')
>>> f
<_io.TextIOWrapper name='sample.txt' encoding='latin-1'>
>>> f.write('Hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.
>>>
detach() 方法会断开文件的最顶层并返回第二层,之后最顶层就没什么用了。例如:
>>> f = open('sample.txt', 'w')
>>> f
<_io.TextIOWrapper name='sample.txt' mode='w' encoding='UTF-8'>
>>> b = f.detach()
>>> b
<_io.BufferedWriter name='sample.txt'>
>>> f.write('hello')
Traceback (most recent call last):File "<stdin>", line 1, in <module>
ValueError: underlying buffer has been detached
>>>
一旦断开最顶层后,你就可以给返回结果添加一个新的最顶层。比如:
>>> f = io.TextIOWrapper(b, encoding='latin-1')
>>> f
<_io.TextIOWrapper name='sample.txt' encoding='latin-1'>
>>>
尽管已经向你演示了改变编码的方法,但是你还可以利用这种技术来改变文件行处理、错误机制以及文件处理的其他方面。例如:
>>> sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='ascii',
... errors='xmlcharrefreplace')
>>> print('Jalape\u00f1o')
Jalapeño
>>>
注意下最后输出中的非 ASCII 字符 ñ 是如何被 ñ 取代的。
《Python Cookbook 3rd》笔记(5.16):增加或改变已打开文件的编码相关推荐
- 《Python Cookbook 3rd》笔记汇总
文章目录 一.数据结构 二.字符串和文本 三.数字.日期和时间 四.迭代器与生成器 五.文件与IO 一.数据结构 标题 关键词 1.1:拆分序列后赋值给多个变量 可迭代对象.拆分赋值 1.2:拆分任意 ...
- 《Python Cookbook 3rd》笔记(1.4):查找最大或最小的N个元素
<Python Cookbook 3rd>1.4:查找最大或最小的N个元素 问题 怎样从一个集合中获得最大或者最小的N个元素列表? 解法 heapq 模块有两个函数:nlargest()和 ...
- 《Python cookbook》笔记二
<Python cookbook>笔记二 第二章 字符串和文本 -使用多个界定符分割字符串- 你需要将一个字符串分割为多个字段,但是分隔符 (还有周围的空格) 并不是固定 的. # str ...
- Machine Learning with Python Cookbook 学习笔记 第8章
Chapter 8. Handling Images 前言 本笔记是针对人工智能典型算法的课程中Machine Learning with Python Cookbook的学习笔记 学习的实战代码都放 ...
- Machine Learning with Python Cookbook 学习笔记 第6章
Chapter 6. Handling Text 本笔记是针对人工智能典型算法的课程中Machine Learning with Python Cookbook的学习笔记 学习的实战代码都放在代码压缩 ...
- Python Cookbook 3rd Edition Documentation
Python Cookbook 3rd Edition Documentation 文章目录 第一章:数据结构和算法 1.1 解压序列赋值给多个变量 问题 解决方案 讨论 1.2 解压可迭代对象赋值给 ...
- Machine Learning with Python Cookbook 学习笔记 第9章
Chapter 9. Dimensionality Reduction Using Feature Extraction 前言 本笔记是针对人工智能典型算法的课程中Machine Learning w ...
- 《Python Cookbook 3rd》笔记(5.18):将文件描述符包装成文件对象
将文件描述符包装成文件对象 问题 你有一个对应于操作系统上一个已打开的 I/O 通道 (比如文件.管道.套接字等)的整型文件描述符,你想将它包装成一个更高层的 Python 文件对象. 解法 一个文件 ...
- 《Python Cookbook 3rd》笔记(5.1):读写文本数据
读写文本数据 问题 你需要读写各种不同编码的文本数据,比如 ASCII,UTF-8 或 UTF-16 编码等. 解法 使用带有 rt 模式的 open() 函数读取文本文件(t表示text文本模式,默 ...
最新文章
- python 归一化_只需 45 秒,Python 给故宫画一组手绘图!
- quartz 两个java_spring boot整合quartz实现多个定时任务的方法
- 几个比较实用的CSS
- 百度单测生成技术如何召回线上服务的异常问题?
- 音视频技术开发周刊 | 132(FFmpeg决策委员会委员 刘歧)
- sap获取系统时间_获取系统当前时间
- mysql datetime timestamp 索引_MYSQL中时间类型底层存储,DATETIME ,TIMESTAMP,INT 如何选择?...
- SQLite | Where 子句
- python 代码_如何让Python代码加速运行?
- STemwin替换为MDK下的emwin
- 网易云api及 asrsea 加密参数文档
- 自动化查询及增加配置参数功能
- java 数独 gui,GitHub - fagen/sudoku: 数独终局生成器和GUI
- 上交所实时行情文件汇总
- Day9 化学方程式配平
- 公司股权外部转让流程
- 【愚公系列】2023年06月 网络安全(交通银行杯)-木册木兰
- 哪家宽带网速是最好最快的?
- 对于给定的正整数N,需要计算 S=1!+2!+3!+...+N!
- linux中常见的校验用正则表达式
热门文章
- java递增_java-8 – 如何按组递增
- 正确断开计算机和网络的方法是,网络管理与维护-题库
- 卸载idea_IDEA 不为人知的 5 个骚技巧!真香!
- CSS一个元素同时使用多个类选择器(class selector)
- iis运行原理 Asp.Net详解IIS内部运行原理
- 【转】VSTS中版本控制系统Git与TFVC的区别
- 一步步编写操作系统 55 CPL和DPL入门2
- 投标报价得分计算程序_什么是投标报价?怎么计算呢?
- Coding Pages 申请 SSL 证书错误:urn:acme:error:unauthorized: Invalid response from http://xxxxx/
- mysql 事务实例_mysql实现事务的提交和回滚实例