python - 这个技巧如何通过删除 C 库来暴露 Python 库?(允许猴子修补 ElementTree)
问题描述
我想对 ElementTree 进行猴子补丁,因为它太有限了,而且我有一段代码可以工作,但我不明白,所以可能很危险(跨平台?版本问题?已弃用?Python4 兼容性?等等),所以我想了解它。
ElementTree.Element
由于它是在 C 中实现的(见脚注),因此不能轻易修补,但“暴露隐藏的 Python 模块有效”。以下代码块来自 module xmlschema
,它意外且神奇地放置在 ElementTree 的导入之前,使导入的ElementTree.Element
monkeypatchable。这段代码的原因是:
import sys, importlib
sys.modules.pop('xml.etree.ElementTree', None)
sys.modules['_elementtree'] = None
ET = importlib.import_module('xml.etree.ElementTree')
因此,该模块正在从系统中删除。但是无论如何 importlib 都会导入它。
文档说:
这两个函数最重要的区别是import_module()返回的是指定的包或模块(如pkg.mod),而import ()返回的是顶层包或模块(如pkg)。
但我没有指定一个包......
- importlib 不检查字典 sys.modules 吗?
- 这个技巧是普遍安全的还是危险的?(适用于
import lxml
失败的 Mac py 3.7 和有效的 Win 3.4)
C 实现的 ET.element 脚注
这是无法对 ET.Element 进行猴子补丁的示例。
>>> import xml.etree.ElementTree as ET
>>> ET.Element.new = 'anything'
TypeError: can't set attributes of built-in/extension type 'xml.etree.ElementTree.Element'
class newElement(ET.Element):
new = 'hello world'
>>> ET.Element = newElement
>>> elem = ET.fromstring('<xml><hello>world</hello></xml>')
AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'new'
>>> type(newElement()) # should be
>>> type(elem) # but isn't
解决方案
推荐阅读
- pdf - ps2pdf时gsview 9.27发生了什么
- laravel - 如何从larvel框架模型中的表中获取数据并直接在视图中使用?
- react-native - 在本机反应中添加长按事件
- php - 覆盖 Laravel 5.2 上的 phpunit
- ios - 在 XCode 上需要帮助:线程 1:EXC_BAD_INSTRUCTION (WebView)
- go - 从选择插入时缓冲通道不阻塞的正确方法是什么?在 goroutine 中做这件事是一种反模式吗
- java - java.sql.SQLException: 无法获得连接,池错误 Timeout waiting for idle object 。如何恢复连接
- mysql - 如何获得精确插入行的 auto_increment 主键?
- c - 用于获取远程服务器主机名的 Linux C API?
- c++ - lex/flex 实现 C/C++ 嵌套`#include "Header"` 语法的解释?