事件处理程序中的 Python Kivy PicklingError:无法腌制 <type 'code'>:属性查找 __builtin__.code 失败

Posted

技术标签:

【中文标题】事件处理程序中的 Python Kivy PicklingError:无法腌制 <type \'code\'>:属性查找 __builtin__.code 失败【英文标题】:Python Kivy PicklingError within event handler: Can't pickle <type 'code'>: attribute lookup __builtin__.code failed事件处理程序中的 Python Kivy PicklingError:无法腌制 <type 'code'>:属性查找 __builtin__.code 失败 【发布时间】:2016-03-15 03:25:04 【问题描述】:

我是 Kivy 和多处理的新手。

我正在探索同时运行多个 Kivy 应用程序,使用多处理,方式与以下相同:Running multiple Kivy apps at same time that communicate with each other。

现在,我想维护当前运行的应用程序的共享列表,例如 Manager.list(),但我一开始就卡住了。我有一个这样的测试代码:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label

from multiprocessing import Process, Manager


class ParentApp(App):
    def __init__(self, app_list, **kwargs):
        super(ParentApp, self).__init__(**kwargs)
        self.app_list = app_list

    def build(self):
        self.add_self_to_list()
        return Label(text = "abc")

#   def on_start(self):
#       self.add_self_to_list()

    def add_self_to_list(self):
        self.app_list.append(self)


if __name__ == "__main__":
    manager = Manager()
    my_list = manager.list()

    print "Before:"
    print my_list

    parent = ParentApp(my_list)

    p = Process(target = parent.run)
    p.start()
    p.join()

    print "After:"
    print my_list

这会将ParentApp 正确添加到共享的my_list,但是当我在build 中注释掉self.add_self_to_list() 并取消注释on_start 时,我得到了这个PicklingError:

...
self.app_list.append(self)
File "<string>", line 2, in append
File "C:\Kivy-1.9.0-py2.7-win32-x64\Python27\lib\multiprocessing\managers.py", line 758, in _callmethod
    conn.send((self._id, methodname, args, kwds))
PicklingError: Can't pickle <type 'code'>: attribute lookup __builtin__.code failed

我还尝试将add_self_to_list 挂钩到按钮的on_press 回调,但我得到了同样的错误。为什么它适用于 build 方法而不适用于回调?有没有办法解决这个问题?

我在 Windows 7 上运行 Kivy 1.9.0 和 Python 2.7。

(如果您想知道我为什么要这样尝试:每个应用程序都可能调用其他应用程序。如果一个应用程序已经在运行,我不想启动一个新应用程序并用副本污染屏幕同一个窗口。理想情况下,我会抓住应用程序并在前面弹出它的窗口。我还没有尝试过 Kivy 应用程序的 root_window,所以我什至不确定这是否可能。只是查看选项在这里 :) 如果您已经知道这是否可以使用 Kivy 完成,我也想知道,但也许我会发布另一个问题! )

【问题讨论】:

【参考方案1】:

我不知道kivy 是否有任何特殊限制,但你不能腌制一个code 对象用于multiprocessing。但是,multiprocessing 的一个分支(称为multiprocess)使用可以腌制code 对象的序列化程序(dill)。所以,multiprocess 应该有机会为你工作。

>>> import multiprocess
>>> CodeType = compile('','','exec')
>>> f = lambda x:CodeType
>>> p = multiprocess.Pool()
>>> p.map(f, range(2))
[<code object <module> at 0x100aeb5b0, file "", line 1>, <code object <module> at 0x100af1130, file "", line 1>]

顺便说一句,我建议不要腌制 GUI 类实例,而是从 GUI 中提取和转储状态。

【讨论】:

注意,我是multiprocess的作者。 谢谢迈克,我现在才看到你的回答。我会尽快尝试,然后再回来找你。

以上是关于事件处理程序中的 Python Kivy PicklingError:无法腌制 <type 'code'>:属性查找 __builtin__.code 失败的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能从 Kivy 终止这个 Python 多处理进程?

Kivy 中的 HTTPS 请求

Python/Kivy:如何在 ctrl+a 键盘事件上调用函数

使用python / kivy处理小部件放置以解决屏幕旋转的好方法是啥?

python中的Kivy弹出窗口,按钮上有多个on_release操作

为啥 Kivy 需要括号,而 Python 不需要括号?