繁体   English   中英

如何控制在取消python对象时导入的内容?

[英]How to control what gets imported when you unpickle python object?

我有以下设置:

a.py

class A(object):
    def __init__(self, name):
        self.name = name
    def a(self):
        print('yow {}!'.format(self.name))

b.py

class B(object):
    def __init__(self, obj):
        self.obj = obj

sender.py

from a import A
from b import B
message = pickle.dumps(B(A('Martin')))

receiver.py

my_b = pickle.loads(message)
my_a = my_b.obj
my_a.a()

输出: yow Martin!

sender.py我酸洗对象b充当该对象的载体a 然后我通过RabbitMQ将腌制对象b发送到另一个进程 receiver.py (这是另一个进程)中,我通过RabbitMQ获取消息,unpickle对象b和魔术BA自动导入。 我能控制进口的东西吗? 我希望工作者receiver.py尽可能少地使用内存。 但是如果模块在没有我控制的情况下导入,它会很快变得臃肿。

有人可以解释泡菜是如何进口的,以及如何处理它?

它使用AB__module__属性:

>>> A.__module__
'a'
>>> __import__(A.__module__)
<module 'a' from 'a.py'>

如果要控制导入的内容,可以构造python包,以便from a import A加载太多对象。

需要什么样的控制? 正如您从源代码中看到的,当您运行pickle.loads(content)它实际上会:

def loads(str):
    file = StringIO(str)
    return Unpickler(file).load()

然后有一些魔力。 它将字符串作为文件读取并调度其内容基于特定的键:

GLOBAL          = 'c'   # push self.find_class(modname, name); 2 string args
INST            = 'i'   # build & push class instance

加载功能本身:

def load(self):
    """Read a pickled object representation from the open file.
    Return the reconstituted object hierarchy specified in the file.
    """
    ...
    read = self.read  # self.read = file.read, which is StringIO's read()
    dispatch = self.dispatch
    try:
        while 1:
            key = read(1)
            dispatch[key](self) # this function call makes a future import.
   except _Stop, stopinst:
       return stopinst.value

您对方法find_class()感兴趣,该方法在其他几个load functionsload_inst()load_global() )中使用:

def find_class(self, module, name):
    # Subclasses may override this:
    __import__(module)  # straight-forward import, you can ovveride it.
    mod = sys.modules[module]
    klass = getattr(mod, name)
    return klass

例如, load_inst()函数:

def load_inst(self):
    module = self.readline()[:-1]
    name = self.readline()[:-1]
    klass = self.find_class(module, name)
    # Now module is imported and ready to be used:
    self._instantiate(klass, self.marker())
dispatch[INST] = load_inst

因此,如果要控制可导入的名称空间或模块,则需要对Unpickler进行子类Unpickler并覆盖find_class()以适合您的目标。 我的回答对你有帮助吗?

pickle需要导入模块ab ,以便加载重新构建对象所需的类AB 我拿了你的例子,只是将a.py重命名为aaaa.py,将b.py重命名为bbbb.py. 现在,如果我们打印sender.py实际发送的消息(pickled对象),你会看到:

ccopy_reg
_reconstructor
p0
(cbbbb
B
p1
c__builtin__
object
p2
Ntp3
Rp4
(dp5
S'obj'
p6
g0
(caaaa
A
p7
g2
Ntp8
Rp9
(dp10
S'name'
p11
S'Martin'
p12
sbsb.

你不需要理解所有这些,但请注意bbbb后跟Baaaa后跟A在那里。 那就是告诉pickle如何重建你的腌制对象。 为了加载类,它必须导入定义类的模块。如果你试图搞乱pickle的机器并阻止模块被加载,那么将无法重建你的对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM