当前位置: 首页 > 面试题库 >

如何在运行时制作python模块的副本?

姬自强
2023-03-14
问题内容

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

这可能吗?

我的意思是真正地复制一个模块,即在 运行时
获得与复制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被弃用python3.3
+
,并建议使用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调用的第一个参数。请查看文档以了解详细信息。

更新:

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

下面是另一个强调这一点的示例。

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

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'


 类似资料:
  • 问题内容: 许多第三方Python模块都有一个属性,该属性保存该模块的版本信息(通常类似或),但有些则不然。 此类模块的特定示例是libxslt和libxml2。 我需要检查这些模块在运行时是否使用了正确的版本。有没有办法做到这一点? 潜在的解决方案是在运行时读取源代码,对其进行哈希处理,然后将其与已知版本的哈希进行比较,但这很讨厌。 有更好的解决方案吗? 问题答案: 我会远离哈希。正在使用的li

  • 问题内容: 该变量很方便,部分原因是它会影响每个模块。如果我想创建另一个工作方式相同的变量,我该怎么做? 从某种意义上说,如果我在一个模块中更改foo,而在其他模块中对其进行更新,则该变量(让我们为原始变量,并将其称为“ foo”)不必是真正全局的。如果我可以在导入其他模块之前设置foo,然后它们会看到相同的值,那很好。 问题答案: 我不以任何方式,形状或形式认可该解决方案。但是,如果你将变量添加

  • 包括目录中的所有模块,而中的模块通过包括 在运行时,上面的操作很好。但是,和也作为它们自己的脚本工作,但是运行会出现错误 从导入中删除可以使各个脚本正常工作,但主脚本找不到。 我如何使导入对主程序和单个模块都起作用?

  • 问题内容: 是2D数组。我想要一个新变量,其值与数组相同。此外, 使用Y进行的任何其他操作都不应影响X的值。 在我看来使用起来很自然。但是它不适用于数组。如果我这样做,然后更改y,x也会更改。我发现问题可以这样解决: 但是它不适用于2D阵列。例如: 返回。如果我替换为,这也无济于事。 有人知道什么是正确且简单的方法吗? 问题答案: 尝试这个: 我不确定,也许就足够了。

  • 问题内容: 我有一个正在构建的Python程序,可以通过以下两种方式之一运行:第一种是调用,它以友好的方式提示用户输入,然后通过该程序运行用户输入。另一种方法是调用“ ”,它将遍历所有友好的输入集合,并通过该程序一次运行整个文件的输入值。 问题是,当我运行时,它会从中导入一些变量/方法/等,并在运行此代码时: 在程序的第一行,它立即错误,因为它试图运行中的代码。 如何阻止Python运行要导入的“