2017-08-20 54 views
1

这是我试图做的最小版本。这是我的main.py文件:Kivy UrlRequest不触发回调

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) 
     ... 

这是包含DownloadTask我task.py文件。

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中的第47行在尝试访问self.proxy时引发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()垃圾收集了吗?

Environemnt:Python的3.5.3,Kivy 1.10.0,MAC OS

回答

2

编辑:source被揭露后,在我看来,这是垃圾收集DownloadTask对象,因此Thread通过跑UrlRequestcalled a WeakProxy对于不存在的对象的方法 - 因此崩溃。


无论是垃圾收集或没有我不知道,但是请求创建一个守护进程Thread,所以你不应该想那么多(随便看看)。有关于它的comment,所以它可能不是收集而是

然而,UrlRequest强烈依赖于基维,这是可见的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()) 
+0

实际上'UrlRequest._dispatch_result()'被调用。而且我不会从kivy应用上下文中调用这些代码。如果你想看,这是源。 https://github.com/eteamin/Exmoore/blob/master/models/task.py ,这是主文件https://github.com/eteamin/Exmoore/blob/master/main.py – Juggernaut

+0

我看到。然后在[这种情况下](https://github.com/eteamin/Exmoore/blob/b01df0ce5bfab9d38849877f76e3e6e0b2127cab/main.py#L38)我相信你的*'DownloadTask' *对象被收集。 – KeyWeeUsr

+0

另外,如果我设置一个函数而不是一个方法作为回调,该函数将被调用 – Juggernaut