如何在运行时复制Python模块?

2024-01-30

我需要制作一个套接字模块的副本才能使用它,并再对一个套接字模块进行猴子修补并以不同的方式使用它。

这可能吗?

我的意思是真正复制一个模块,即得到相同的结果runtime就好像我复制了一样socketmodule.c, 改变了initsocket()功能为initmy_socket(),并将其安装为my_socket扩大。


您始终可以使用一些技巧,例如导入模块然后从 sys.modules 中删除它或尝试复制模块。然而,Python 已经在其标准库中提供了您想要的内容。

import imp # Standard module to do such things you want to.

# We can import any module including standard ones:
os1=imp.load_module('os1', *imp.find_module('os'))

# Here is another one:
os2=imp.load_module('os2', *imp.find_module('os'))

# This returns True:
id(os1)!=id(os2)

Python3.3+

imp.load_module is 在 python3.3+ 中已弃用 https://docs.python.org/3/library/imp.html#imp.load_module,并建议使用importlib

#!/usr/bin/env python3

import sys
import importlib.util

SPEC_OS = importlib.util.find_spec('os')
os1 = importlib.util.module_from_spec(SPEC_OS)
SPEC_OS.loader.exec_module(os1)
sys.modules['os1'] = os1

os2 = importlib.util.module_from_spec(SPEC_OS)
SPEC_OS.loader.exec_module(os2)
sys.modules['os2'] = os2
del SPEC_OS

assert os1 is not os2, \
    "Module `os` instancing failed"

在这里,我们将同一模块导入两次,但作为完全不同的模块对象。如果检查 sys.modules,您可以看到作为 load_module 调用的第一个参数输入的两个名称。看看文档 http://docs.python.org/library/imp.html了解详情。

UPDATE:

为了使这种方法的主要区别显而易见,我想更清楚地说明这一点:当您以这种方式导入相同的模块时,您在运行时导入的每个其他模块都可以全局访问两个版本,这正是提问者所需要的我明白了。

下面是另一个例子来强调这一点。

这两个语句做了完全相同的事情:

import my_socket_module as socket_imported

socket_imported = imp.load_module('my_socket_module',
    *imp.find_module('my_socket_module')
)

在第二行,我们重复“my_socket_module”字符串两次,这就是 import 语句的工作原理;但事实上,这两个字符串有两个不同的原因。

我们将其传递给 find_module 时的第二次出现用作将在系统上找到的文件名。我们将字符串传递给 load_module 方法时第一次出现的字符串用作加载模块的系统范围标识符.

因此,我们可以为它们使用不同的名称,这意味着我们可以让它像复制模块的 python 源文件并加载它一样工作。

socket = imp.load_module('socket_original', *imp.find_module('my_socket_module'))
socket_monkey = imp.load_module('socket_patched',*imp.find_module('my_socket_module'))

def alternative_implementation(blah, blah):
    return 'Happiness'

socket_monkey.original_function = alternative_implementation

import my_sub_module

然后在 my_sub_module 中,我可以导入系统上不存在的“socket_patched”!我们在 my_sub_module.py 中。

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

如何在运行时复制Python模块? 的相关文章

随机推荐

  • 使用脚本编辑器将表情符号 unicode 从 Google 表格插入到电子邮件中

    我正在尝试使用脚本编辑器从谷歌表格中获取一些文本来发送电子邮件 该文本包含表情符号 unicode 但是 当发送电子邮件时 它会打印纯文本而不是显示 unicode 表情符号 我在电子邮件中看到的内容 9889 some text here
  • Boost.Spirit:解析期间设置子语法

    为了处理大量的编译时间和语法的重用 我将语法组成了几个按顺序调用的子语法 其中之一 称为 SETUP 语法 提供了解析器的一些配置 通过符号解析器 因此后面的子语法在逻辑上依赖于该语法 再次通过不同的符号解析器 因此 在解析SETUP之后
  • 控制台应用程序 - DbContext 实例不能在 OnConfiguring 内部使用

    我正在使用 Asp Net Core 控制台应用程序 Entity Framework Core 和工作单元存储库模式 当我使用多线程函数时 出现以下错误 DbContext 实例不能在 OnConfiguring 内部使用 因为此时它仍在
  • 通过作业运行 SP 时响应数据截断

    Subject 我每个月都会创建一份报告 报告的创建包括 2 个步骤 从我们的服务获取 XML 并将其存储在数据库中 解析 XML 并创建文件 在过去的几个月里 我以手动模式创建了报告 现在我想自动化这些东西 但这里来了一个 Problem
  • Linq to objects - 选择第一个对象

    我对linq几乎一无所知 我正在这样做 var apps from app in Process GetProcesses where app ProcessName Contains MyAppName app MainWindowHan
  • 如何将 Scala Spark Dataset.show 重定向到 log4j 记录器

    Spark API 文档展示了如何从发送到 stdout 的数据集或数据帧中获取漂亮的打印片段 可以将此输出定向到 log4j 记录器吗 或者 有人可以分享将创建类似于 df show 格式的输出的代码吗 有没有办法做到这一点 允许 std
  • 如何为每个 git 存储库管理一个唯一的密钥?

    我在两种情况下使用git 我用一些Github存储库 我目前正在使用 OpenShift 它使用ssh and git用于部署 首先 我用了ssh keygen用于生成在 OpenShift 站点更新的密钥 这样的密钥存储在 ssh 并创造
  • 如何从类库中的头项目的 app.config/appsettings.json 获取连接字符串

    在编写访问数据库的 C 类库时 我从头项目的 app config appsettings json 获取连接字符串的首选方法是让数据库访问类依赖于某些IConnectionString由 head 项目在 IOC 容器中注册的接口 然而
  • Gatsby 与 PostCSS 8 - 尝试导入错误:“component.module.css”不包含默认导出(作为“样式”导入)

    我有一个基于入门项目的 Gatsby and Sanity 网站 到目前为止 一切都很顺利 但我今天在 package json 文件中更新了所有软件包和插件 以消除所有 npm 警告 这包括更新到 Gatsby 3 0 3 和 PostC
  • 获取给定 AnyObject 的唯一字符串?

    在 Objective C 中 这很简单 NSString stringWithFormat p objRef 我怎样才能在斯威夫特做到这一点 func hashString obj AnyObject gt String return S
  • 用于确定 n 是否完全平方的 O(log log n) 算法

    是否有已发布的 O log b 算法来确定 b 位数字是否为整数的平方 如果这个问题超出了本网站的范围 我深表歉意 如果是的话 我很乐意检索它 更新 我意识到我提出的问题是不合理的 因此 让我通过询问 b 中的次多项式运算的任何算法来修改它
  • 如何在 Material-UI 中插入新行?

    我正在开发一个联系人应用程序 其中所有数据都临时存储在客户端 我使用了 Material ui 表来显示联系人 当单击右下角的 添加新联系人 按钮时 它会显示一个带有表单的对话框 单击 保存 按钮时 数据将保存在该状态中 但我面临的问题是如
  • primeng 下拉组件错误(“p-dropdown”不是已知元素)

    遵循指南 https www primefaces org primeng https www primefaces org primeng 我尝试按照上面详述的步骤安装 PrimeNG 以与 Angular4 一起使用 但出现错误 p d
  • Jquery + Rails 有问题,是真的吗?

    我在上一个问题中看到评论说最好将 Prototype 与 Rails 一起使用 然而 我自己的经验是 Jquery 是一个优秀的 Javascript 库 作为 Rails 的新手 我还没有研究如何将 Jquery 与 Rails 一起使用
  • 在新订单电子邮件通知中显示客户 IP 地址

    创建新订单时 woocommerce 将向管理员发送一封电子邮件 我希望它也在电子邮件中发送客户的 IP 地址 但我无法让它工作 这是我到目前为止得到的 这段代码进入mytheme woocommerce emails admin new
  • Installshield主要升级不会卸载旧版本

    我有一个 Installshield 项目 我添加了一个主要的升级项目并进行了更改Product version Product code and Package code 使用新安装程序安装后 旧版本仍然存在 在Add Remove 我认
  • Python Dataframes 未合并索引

    我正在尝试合并 2 个数据帧 但由于某种原因它抛出KeyError Player Id 我正在尝试合并Striker Id and Player Id 这就是我的数据框的样子 合并代码 player runs merge matches p
  • nginx 反向代理导致 POST 请求正文丢失

    我使用 nginx 作为 http 服务的反向代理 使用如下配置 location jobexecutor proxy pass http jobexecutor 8080 jobexecutor proxy set header Host
  • 使用 rspec 测试设备视图

    我已经生成了 Devise 的视图运行rails g devise views现在想测试它们 这就是我想出的 require spec helper describe devise sessions new do before do ren
  • 如何在运行时复制Python模块?

    我需要制作一个套接字模块的副本才能使用它 并再对一个套接字模块进行猴子修补并以不同的方式使用它 这可能吗 我的意思是真正复制一个模块 即得到相同的结果runtime就好像我复制了一样socketmodule c 改变了initsocket