使用 io.TextIOWrapper 包装打开的流

2024-01-08

如何包装一个开放的二进制流 – Python 2file,Python 3io.BufferedReader, an io.BytesIO– 在一个io.TextIOWrapper?

我正在尝试编写不改变即可工作的代码:

  • 在 Python 2 上运行。
  • 在 Python 3 上运行。
  • 使用从标准库生成的二进制流(即我无法控制它们是什么类型)
  • 将二进制流制作为测试双打(即没有文件句柄,无法重新打开)。
  • 生产一个io.TextIOWrapper包装指定的流。

The io.TextIOWrapper之所以需要,是因为标准库的其他部分需要它的 API。存在其他类似文件的类型,但不提供正确的 API。

Example

将二进制流包装为subprocess.Popen.stdout属性:

import subprocess
import io

gnupg_subprocess = subprocess.Popen(
        ["gpg", "--version"], stdout=subprocess.PIPE)
gnupg_stdout = io.TextIOWrapper(gnupg_subprocess.stdout, encoding="utf-8")

在单元测试中,流被替换为io.BytesIO实例来控制其内容而不触及任何子进程或文件系统。

gnupg_subprocess.stdout = io.BytesIO("Lorem ipsum".encode("utf-8"))

这在 Python 3 标准库创建的流上运行良好。但是,相同的代码在 Python 2 生成的流上失败:

[Python 2]
>>> type(gnupg_subprocess.stdout)
<type 'file'>
>>> gnupg_stdout = io.TextIOWrapper(gnupg_subprocess.stdout, encoding="utf-8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'file' object has no attribute 'readable'

不是解决方案:特殊处理file

一个明显的反应是在代码中建立一个分支来测试流是否实际上是 Python 2file对象,并以不同的方式处理该对象io.*对象。

对于经过良好测试的代码来说,这不是一个选项,因为它创建了一个进行单元测试的分支——为了尽可能快地运行,不得创建任何real文件系统对象 – 无法执行。

单元测试将提供测试替身,而不是真实的file对象。因此,创建一个不会被这些测试替身执行的分支会破坏测试套件。

不是解决方案:io.open

一些受访者建议重新开放(例如io.open) 底层文件句柄:

gnupg_stdout = io.open(
        gnupg_subprocess.stdout.fileno(), mode='r', encoding="utf-8")

这适用于 Python 3 和 Python 2:

[Python 3]
>>> type(gnupg_subprocess.stdout)
<class '_io.BufferedReader'>
>>> gnupg_stdout = io.open(gnupg_subprocess.stdout.fileno(), mode='r', encoding="utf-8")
>>> type(gnupg_stdout)
<class '_io.TextIOWrapper'>
[Python 2]
>>> type(gnupg_subprocess.stdout)
<type 'file'>
>>> gnupg_stdout = io.open(gnupg_subprocess.stdout.fileno(), mode='r', encoding="utf-8")
>>> type(gnupg_stdout)
<type '_io.TextIOWrapper'>

但当然它依赖于重新打开真实文件从它的文件句柄。因此,当测试替身是一个时,它会在单元测试中失败io.BytesIO实例:

>>> gnupg_subprocess.stdout = io.BytesIO("Lorem ipsum".encode("utf-8"))
>>> type(gnupg_subprocess.stdout)
<type '_io.BytesIO'>
>>> gnupg_stdout = io.open(gnupg_subprocess.stdout.fileno(), mode='r', encoding="utf-8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
io.UnsupportedOperation: fileno

不是解决方案:codecs.getreader

标准库还具有codecs模块,它提供包装器功能:

import codecs

gnupg_stdout = codecs.getreader("utf-8")(gnupg_subprocess.stdout)

这很好,因为它不会尝试重新打开流。但它未能提供io.TextIOWrapperAPI。具体来说,它不继承io.IOBase and 没有encoding属性:

>>> type(gnupg_subprocess.stdout)
<type 'file'>
>>> gnupg_stdout = codecs.getreader("utf-8")(gnupg_subprocess.stdout)
>>> type(gnupg_stdout)
<type 'instance'>
>>> isinstance(gnupg_stdout, io.IOBase)
False
>>> gnupg_stdout.encoding
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/codecs.py", line 643, in __getattr__
    return getattr(self.stream, name)
AttributeError: '_io.BytesIO' object has no attribute 'encoding'

So codecs不提供替代对象io.TextIOWrapper.

该怎么办?

那么我怎样才能编写适用于 Python 2 和 Python 3 的代码,同时包含测试替身和真实对象,这包裹一个io.TextIOWrapper围绕已经打开的字节流?


Use 编解码器.getreader https://docs.python.org/3/library/codecs.html#codecs.getreader生成包装对象:

text_stream = codecs.getreader("utf-8")(bytes_stream)

适用于 Python 2 和 Python 3。

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

使用 io.TextIOWrapper 包装打开的流 的相关文章

  • 如何修复 Apache mod_wsgi 的 Python 版本不匹配问题?

    我收到此错误 Thu Jul 12 14 31 36 2012 error python init Python version mismatch expected 2 6 7 found 2 6 8 当尝试启动 Apache 服务器时 在
  • 重新索引错误没有意义

    I have DataFrames大小在 100k 到 2m 之间 我正在处理这个问题的框架是如此之大 但请注意 我必须对其他框架执行相同的操作 gt gt gt len data 357451 现在这个文件是通过编译许多文件创建的 所以它
  • 蜘蛛内的Scrapyd jobid值

    Scrapy 框架 Scrapyd 服务器 我在获取蜘蛛内部的 jobid 值时遇到一些问题 将数据发布到后http localhost 6800 schedule json http localhost 6800 schedule jso
  • Spyder 导入模块出错

    我正在尝试在 Spyder 中使用 sklearn 一开始 当我尝试导入它时 我收到 ImportError No module named sklearn 然后我用 PYTHONPATH 管理器设置 PATH 然后使用工具菜单中的 更新模
  • 如何使用 HTTP 标头发送非英语 unicode 字符串?

    我是 HTTP 相关问题的新手 我的问题是在 iOS 开发中 我想使用 HTTP 标头发送一个字符串 所以我使用 httpRequest setValue nonEnglishString forHTTPHeaderField custom
  • Django 未在 404 页面上应用应用程序中的 CSS 文件

    姜戈3 0 8 Python 3 7 x 我有一个包含一些应用程序的 Django 项目 我正在尝试为 400 403 404 500 错误制作一些 默认 错误页面 我已经这样做了 并显示了适当的模板 但没有任何样式或 JS 在 404 错
  • 了解 asyncio 已经运行的永久循环和挂起的任务

    我在理解如何将新任务挂起到已经运行的事件循环中时遇到问题 这段代码 import asyncio import logging asyncio coroutine def blocking cmd while True logging in
  • 类型错误:需要 Future 或协程

    我尝试在 asyncssh 上自动重新连接 ssh 客户端 SshConnectManager 必须留在后台并在需要时进行 ssh 会话 class SshConnectManager object def init self host u
  • Flask 中的 import 和 extends 有什么区别?

    我正在阅读 Flask Web 开发 在例4 3中 extends base html import bootstrap wtf html as wtf 我想知道 extends 和 import 有什么区别 我认为它们在用法上很相似 在什
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • PyCharm 无法识别字典值类型

    我有一个简单的代码片段 其中我将字典值设置为空列表 new dict for i in range 1 13 new dict i 现在 如果在下一行的循环内我会输入new dict i 并添加一个点 我希望 PyCharm 向我显示可用于
  • 如何在数据框中绘制包含三列的无向图,形成 3 种不同类型的节点(三方)?

    我正在尝试使用三个不同的列表绘制网络的可视化 这三个列表形成 3 种类型的节点 下面的代码正在运行 如图所示 需要两个列表 用户 ID 评分 但是 我希望我的图表是三部分的 即 user userId review ratings prod
  • PyCharm - 如何挂起所有线程

    我们使用 PyCharm 5 0 1 进行多线程调试 当它在断点处停止时 只有特定线程停止 而所有其他线程继续 这使得 冻结时刻 和检查参数值以及其他线程的当前状态变得困难 当其中一个线程在断点处停止时 是否可以挂起所有线程 这在最新的 P
  • 如何修改 contenteditable 元素的innerHTML

    我使用 Selenium 与 Chrome driver 和 python3 6 来测试网站 我在网页中有代码片段如下 div class 3F6QL 2WovP div class 39LWd Type a message div div
  • 如何加速 pandas 字符串函数?

    我正在使用 pandas 矢量化 str split 方法来提取从 上的拆分 返回的第一个元素 我还尝试使用 df apply 与 lambda 和 str split 来产生等效的结果 使用 timeit 时 我发现 df apply 的
  • 使用 statsmodels.formula.api 中的 ols - 如何删除常数项?

    我正在遵循第一个例子statsmodels教程 http statsmodels sourceforge net devel http statsmodels sourceforge net devel 如何指定在 ols 中不使用常数项进
  • Scrapy 抓取并跟踪 href 中的链接

    我对 scrapy 很陌生 我需要从 url 的主页跟踪 href 到多个深度 再次在 href 链接内我有多个 href 我需要遵循这些href 直到到达我想要抓取的页面 我的页面的示例 html 是 初始页 div class page
  • Matplotlib 中的 TwoSlopeNorm 未按预期工作

    我正在尝试创建一个具有发散颜色图的绘图 该颜色图在零附近不对称 In this https stackoverflow com a 20146989 6288682例如 DivergingNorm函数被使用并产生我想要的 然而 我使用的是更
  • 在多个图表上绘制一条线

    I don t know how this thing is called or even how to describe it so the title may be a little bit misleading The first a
  • django admin 中内联模型的分页器

    我有这个简单的 django 模型 由一个传感器和特定传感器的值组成 每个日射强度计的值数量很多 gt 30k 是否可以以某种方式分页PyranometerValues在特定日期或一般情况下将分页器应用于管理内联视图 class Pyran

随机推荐

  • 重力形式上的 js 错误

    我们在 wpengine 上托管 WordPress 网站 在这个网站上 我们使用重力形式 但由于某种原因它停止工作 我们得到的只是一个 js 错误 Uncaught ReferenceError gformInitSpinner is n
  • 从字符串创建 DOM 文档,无需使用 JQuery

    我们正在寻找方法来创建DOM文档在 javascript 中从字符串中读取 但不使用 Jquery 有办法这样做吗 我认为是这样 因为 Jquery 可以做到 对于那些好奇的人来说 我们不能使用 Jquery 因为我们是在 Chrome 应
  • NodeJS 语法错误:JSON 中位置 0 处出现意外标记

    The bodyAuthorize net 的沙箱 API 的响应是 messages resultCode Error message code E00012 text You have submitted a duplicate of
  • 云源存储库的 HEAD 未指向任何提交

    有没有办法配置云源存储库以将 HEAD 指向最新提交 我在云源存储库中创建了一个新存储库 并且 HEAD 没有指向远程存储库 GCP 中的任何内容 尽管在我的本地存储库中 HEAD 确实指向最新的提交 即使我可以看到远程存储库 云源存储库
  • 当视频播放器不在视野范围内时,将 HTML5 视频设置为暂停

    我想用 JavaScript 来做到这一点 我正在使用 Hakim El Hattab 的演示文稿Reveal js http lab hakim se reveal js 作为基础 Reveal js 的工作方式是 您正在查看的当前幻灯片
  • 使用 ffmpeg.js 将 WebM/H.264 高效转换为 MP4/H.264

    由于这里的答案 使用 WebRTC MediaRecorder 录制跨平台 H 264 视频 https stackoverflow com questions 45221112 recording cross platform h 264
  • 如何在 iOS 中注册 GCM

    我似乎无法让 GCM 推送通知正常工作 我的问题是我不知道如何从 GCM 获取注册 ID 我可以从 APN 获得令牌 但我不太确定下一步该做什么 我尝试按照教程进行操作 但它对我来说并不起作用 我是初学者 所以请明确 我想问的是 从 APN
  • 节是柯里化的结果吗?

    Hutton 的 Haskell 编程 一般来说 如果 是一个运算符 那么表达式的形式 x 和 y 用于论证x and y称为节 其作为函数的含义可以是 使用 lambda 表达式形式化如下 x gt y gt x y x y gt x y
  • Restlet流数据

    我正在执行一项任务 我将从设备读取数据并使其通过网络服务可用 每秒读取数据 4 次 我希望 Web 客户端具有开放的 HTTP 连接 并使用以下方式将设备读数作为流获取分块传输 http en wikipedia org wiki Chun
  • VSX?虚拟MX?阿尔蒂维克?虚拟现实?振动时效?!这些 PowerPC SIMD 缩写词之间有何关系?

    我听说过很多关于 Altivec 寄存器的事 但我什至没有在网上找到它POWER9 指令集架构 https www docdroid net tWT7hjD powerisa v30 pdf 在该文档中 我只在第 6 章 矢量设施 和第 7
  • 如何获取 Android 11 中已安装应用的列表

    开发者网站上描述了这一行 但我没有完全理解它 Call getInstalledApplications or getInstalledPackages Both methods should return a filtered list
  • Python 压缩子文件夹而不是整个文件夹路径

    我有一个程序可以将所有内容压缩到一个文件夹中 我没有编写这段代码 但我在网上找到了它并且我正在使用它 我打算压缩一个文件夹 例如 C folder1 folder2 folder3 我想将folder3 及其所有内容压缩到一个文件中 例如f
  • 如何列出从单个卷 ID EC2 实例创建的所有快照?

    在过去的几个月中 我们的快照备份量增加 因此我们每月在亚马逊 EC2 上的账单也随之增加 现在我想删除一些旧的 EC2 快照 所以问题是 如何使用 EC2 命令行工具查找从单个卷 ID 创建的所有快照 I tried ec2 describ
  • 访问另一个类的 Swing 组件

    我有两节课gameWindow and gameEngine 主要方法是在gameWindowclass so 是 swing GUI 代码 现在 我想访问中的 swing 组件gameEngine 怎么做 我总是得到cannot find
  • std::bit_cast 和 std::start_lifetime_as 之间有什么有用的区别吗?

    std bit cast显然是在 c 20 中引入的 和std start lifetime as被提议用于 c 23 来自P0593R5 https wg21 link p0593R5 由于它们似乎都要求所涉及的数据类型无论如何都是微不足
  • 如何在Flutter中复用非Widget类?

    我知道我们应该使用组合优于继承 https stackoverflow com a 51477727 1769177在颤振中 当我们谈论时这很有效Widgets 但是当一个类不是一个类时我该怎么办Widget 例如 我想要我的TextFie
  • 如何在代码隐藏中将 FrameworkElement.Width 属性设置为 QualifiedDouble 的值?

    我试图将我的一个控件的宽度属性设置为qualifiedDouble 如 MSDN 上所述 http msdn microsoft com en us library system windows frameworkelement width
  • Keras Embedding 层中的 mask_zero 如何工作?

    我想mask zero True当输入值为 0 时将输出 0 因此后续层可以跳过计算或其他操作 如何mask zero works 例子 data in np array 1 2 0 0 data in shape gt gt gt 1 4
  • 根据语言更改文本

    我正在使用带有语言切换器的 Wordpress 在各种语言之间进行切换 在模板中 我使用这段代码来切换硬编码文本 This is english This is another language 我有一个侧边栏 但它是通过各种小部件创建的
  • 使用 io.TextIOWrapper 包装打开的流

    如何包装一个开放的二进制流 Python 2file Python 3io BufferedReader an io BytesIO 在一个io TextIOWrapper 我正在尝试编写不改变即可工作的代码 在 Python 2 上运行