【问题标题】:Kivy UrlRequest doesn't trigger callbackKivy UrlRequest 不会触发回调
【发布时间】:2017-08-28 20:51:13
【问题描述】:

这是我正在尝试做的最小版本。这是我的main.py 文件:

class MainScreen(Screen):
    def __init__(self):
        super(MainScreen, self).__init__()
        self.url_input = TextInput()
        self.start = Button(text='Download')

        self.start.bind(on_release=partial(self.on_start_press))
        self.add_widget(self.url_input)
        self.add_widget(self.start)

    def on_start_press(self, *args):
        DownloadTask(self.url_input.text)
        ...

这是我的 task.py 文件,其中包含 DownloadTask

class DownloadTask(object):
    def __init__(self, url):
        self.url = url
        self._get_headers()

    def _get_headers(self):
        UrlRequest(url=self.url, on_success=self._on_headers_fetched, method='HEAD')

    def _on_headers_fetched(self, req, resp):
        self.content_length = int(req.resp_headers.get('Content-Length'))

但永远不会调用 on_success 回调。在urlrequest.py的第439行:

if self.on_success:
    func = self.on_success()
        if func:
            func(self, data)

funcNone,所以不会调用回调。在尝试访问 self.proxy 时,weakmethod.py 中的第 47 行也会引发 ReferenceError: weakly-referenced object no longer exists

try:
    if self.proxy:
        return getattr(self.proxy, self.method_name)
except ReferenceError:
    pass
return self.method

这里有什么问题?我的DownloadTask() 对象被垃圾回收了吗?

环境:Python 3.5.3、Kivy 1.10.0、mac os

【问题讨论】:

    标签: python callback garbage-collection kivy


    【解决方案1】:

    编辑:source 被发现后,在我看来DownloadTask 对象已被垃圾回收,因此ThreadUrlRequest called a @ 运行987654323@ 用于不存在的对象的方法 - 因此崩溃。


    我不确定它是否被垃圾收集,但是该请求会创建一个守护进程Thread,因此您不必太在意(请随意查找)。有一个关于它的comment,所以它可能还没有被收集

    UrlRequest 然而强烈依赖于 Kivy,这是可见的here。它使用 Kivy Clock。这意味着除非 Kivy 应用程序运行,否则请求将不会继续进行,即它应该停止on this line。只需尝试将任何print('something') 添加到UrlRequest._dispatch_result(),您就会看到它被完全忽略了,因为Kivy Clock 没有滴答作响(因此没有调用该函数)。

    但是对于这个示例,实际 Kivy 应用程序在哪里运行,我看不出它有什么问题。

    from kivy.app import runTouchApp
    from kivy.uix.widget import Widget
    from kivy.network.urlrequest import UrlRequest
    
    class My(Widget):
        def __init__(self, **kwargs):
            super(My, self).__init__(**kwargs)
            UrlRequest(
                url='http://lipsum.com/',
                on_error=lambda *args: print('error:', args),
                on_failure=lambda *args: print('fail:', args),
                on_redirect=lambda *args: print('redir:', args),
                on_success=lambda *args: print('success:', args)
            )
    
    runTouchApp(My())
    

    【讨论】:

    • 实际上调用了UrlRequest._dispatch_result()。而且我没有从 kivy 应用程序上下文中调用此代码。如果您想查看,这就是来源。 github.com/eteamin/Exmoore/blob/master/models/task.py 这是主文件github.com/eteamin/Exmoore/blob/master/main.py
    • 我明白了。然后在this case我相信你的DownloadTask对象被收集了。
    • 另外,如果我设置一个函数而不是一个方法作为回调,该函数将被调用
    • 尝试将DownloadTask(...) 更改为self.task = DownloadTask(...) 看看会发生什么。
    • 我就是这样做的,它不再被收集了!谢谢。你能详细说明一下吗?
    猜你喜欢
    • 1970-01-01
    • 2014-01-26
    • 2010-10-09
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    相关资源
    最近更新 更多