我在线程中发现了这个问题:https://bugs.python.org/issue18195
>>> from copy import deepcopy
>>> import types
>>> origin_types = deepcopy(types)
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'update'
如果我真的想要
deepcopy
一个模块,该怎么办?
此外,团队没有实现此功能肯定有某种原因。希望有人可以解释这样做的风险。
[更新]这是我的目的
import os
from copy import deepcopy
from importlib import reload
def disabled_func(f):
def inner(*args, **kwargs):
return f(*args, **kwargs)
return inner
class OSModuleCustomizer(object):
def disable_method(self, os_method):
setattr(os, os_method, disabled_func)
def save_customized_module(self):
self.custom_module = deepcopy(os)
def get_customized_module(self):
return self.custom_module
#original function
os.system("ls") # works
#modifying module
omc = OSModuleCustomizer()
omc.disable_method("system")
os.system("ls") # empty
#saving customized module
omc.save_customized_module();
#reload
reload(__import__("os"))
os.system("ls") # works
#reload saved customized-module
os = omc.get_customized_module()
os.system("ls") # empty
这个答案展示了如何克隆模块。
以下是我的黑客解决方案
sys.modules
。
import importlib
import os
import sys
from importlib import reload
class ModuleCustomizer:
def __init__(self, fullname):
self.custom_module = sys.modules[fullname]
def disable_method(self, method):
setattr(
self.custom_module,
method,
lambda *args, **kwargs: print(
f'{self.custom_module.__name__}: {method} is disabled.')
)
def save_customized_module(self):
fullname = self.custom_module.__name__
spec = importlib.util.find_spec(fullname)
clone = importlib.util.module_from_spec(spec)
spec.loader.exec_module(clone)
sys.modules[fullname] = clone
def get_customized_module(self):
return self.custom_module
#original function
os.system('ls') # works
#modifying module
omc = ModuleCustomizer('os')
omc.disable_method('system')
os.system('ls') # disabled
#saving customized module
omc.save_customized_module()
#reload
os = reload(__import__('os'))
# In this case, below line works too.
# os = reload(sys.modules['os'])
os.system("ls") # works
omc.get_customized_module().system('ls') # disabled
我认为在大多数情况下这可能非常简单。我在尝试深度复制 MLFlow 以登录到两个单独的实例时遇到了类似的问题。
失败来自于无法 pickle 模块(不知道为什么),但 dill 是一个更强大的序列化包,并且似乎工作得很好。
所以就我而言
self._mlflow = dill.copy(mlflow)
刚刚工作。从行为来看,它似乎是一个深层复制,但我还没有进行更彻底的检查。
这篇文章有一些更相关的细节Python:无法pickle模块对象错误