如何控制在解压python对象时导入的内容?

2024-10-05 10:41:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下设置:

a.py

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

b.py

^{pr2}$

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中,我pickle对象b,它充当对象a的载体。然后我通过RabbitMQ将pickled对象b发送到另一个进程。在receiver.py(这是另一个进程)中,我通过RabbitMQ、unpickle objectb和{}自动导入一条消息。我能控制进口什么吗?我希望worker receiver.py尽可能少地消耗内存。但是如果模块没有我的控制就被导入,它会很快膨胀。在

有人能解释一下泡菜是怎么进口的吗?在


Tags: 对象namefrompyimportselfmessagemy
3条回答

它使用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()

还有一些魔力。它将字符串作为文件读取,并根据特定的键发送其内容:

^{pr2}$

加载函数本身:

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

{{cd2>中使用的是{cd3>

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并重写{}以满足您的目标。我的回答对你有帮助吗?在

pickle需要导入模块a和{},以便加载重新构建对象所需的类A和{}。我以你为例,把a.py重命名为aaaa.py公司和b.py tobbbb.py公司. 现在,如果我们打印消息(pickled对象),则发件人.py实际上是在发送,你可以看到:

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后跟B,以及{}然后是{}在那里。它告诉pickle如何重建pickled对象。为了加载类,它必须导入在其中定义类的模块。如果你试图搞乱pickle的机器并阻止加载模块,那么就没有办法重建对象了。在

相关问题 更多 >

    热门问题