2017-08-20 56 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