【问题标题】:Python: How to import package twice?Python:如何两次导入包?
【发布时间】:2015-09-21 06:43:59
【问题描述】:

有没有办法在多线程环境中在同一个 python 会话中以相同的名称但在不同的范围内导入一个包两次?

我想导入包,然后重写它的一些函数来改变它的行为,只有在特定的类中使用。

例如,有没有可能实现这样的目标?

import mod

class MyClass:

  mod = __import__('mod')

  def __init__():
     mod.function = new_function # override module function

  def method():
     mod.function() # call new_function

mod.function() # call original function

这可能看起来很奇怪,但在这种情况下,派生类的用户不必更改其代码即可使用改进的包。

【问题讨论】:

  • 关于这个问题,我想起了我的程序。就像这样:import filename ; print('import')。所以这个程序将自行导入/运行。我认为这会造成无限循环,但它只打印两次import(所以它只导入一次)。
  • 为什么需要mod = __import__('mod') 而不仅仅是mod = mod

标签: python import package


【解决方案1】:

将模块作为副本导入:

def freshimport(name):
    import sys, importlib
    if name in sys.modules:
        del sys.modules[name]
    mod = importlib.import_module(name)
    sys.modules[name] = mod
    return mod

测试:

import mymodule as m1
m2 = freshimport('mymodule')
assert m1.func is not m2.func

注意

importlib.reload 不会做这项工作,因为它总是“周到地”更新旧模块:

import importlib
import mymodule as m1
print(id(m1.func))
m2 = importlib.reload(m1)
print(id(m1.func))
print(id(m2.func))

样本输出:

139681606300944
139681606050680
139681606050680

【讨论】:

  • 感谢您的回答。不幸的是,我不认为这个解决方案允许我在不同的范围内使用 same name 加载相同的模块两次。
  • @Sisyphe 您可以简单地将其绑定到 same local name
【解决方案2】:

这看起来像是上下文管理器的工作

import modul

def newfunc():
    print('newfunc')

class MyClass:
    def __enter__(self):
        self._f = modul.func
        modul.func = newfunc
        return self

    def __exit__(self, type, value, tb):
        modul.func = self._f

    def method(self):
        modul.func()


modul.func()
with MyClass() as obj:
    obj.method()
    modul.func()
modul.func()

输出

func
newfunc
newfunc
func

modul.py 包含在哪里

def func():
    print('func')

注意:此解决方案仅适用于单线程应用程序(OP 中未指定)

【讨论】:

  • 感谢您的回答。此解决方案运行良好,但仅适用于单线程环境。最后输入的对象将始终是全局设置函数的对象。两个线程运行自己的上下文管理器,最后打开的线程将覆盖另一个线程的重新定义(如果我错了,请纠正我)。在这种情况下,覆盖超出了范围。
  • 是的,它是仅适用于单线程应用程序的解决方案。我没有提到它,因为你没有指定这样的约束。已编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
  • 2019-09-11
相关资源
最近更新 更多