Kivy UrlRequest不会触发回调

时间:2017-08-20 10:41:20

标签: python callback garbage-collection kivy

这是我正在努力做的最小版本。这是我的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,因此不会调用回调。在尝试访问weakmethod.py时,ReferenceError: weakly-referenced object no longer exists中的第47行也会引发self.proxy

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

这是什么问题?我的DownloadTask()对象是垃圾收集了吗?

Environemnt:Python 3.5.3,Kivy 1.10.0,mac os

1 个答案:

答案 0 :(得分:2)

修改source显示后,在我看来DownloadTask对象是垃圾收集的,因此Thread运行UrlRequest 1}} called一个WeakProxy用于不存在的对象的方法 - 因此崩溃。

是否是垃圾收集我不确定,但请求会创建一个守护进程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())