2017-08-20 2 views
1

Ceci est une version minimale de ce que j'essaie de faire. Ceci est mon fichier main.py:Kivy UrlRequest ne déclenche pas de rappel

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

Et voici mon fichier task.py qui contient le 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')) 

Mais le rappel on_success n'est jamais appelé. Sur la ligne 439 de urlrequest.py:

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

func est None donc pas de rappel est appelée. En outre, la ligne 47 dans weakmethod.py lève ReferenceError: weakly-referenced object no longer exists en essayant d'accéder à self.proxy.

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

Quel est le problème ici? Ma poubelle d'objet DownloadTask() est-elle collectée?

environemnt: Python 3.5.3, Kivy 1.10.0, mac os

Répondre

2

Edit: Après la source a été révélé, il me semble que l'objet donc DownloadTask a recueilli des ordures, le Thread couru par UrlRequestcalled un WeakProxy pour une méthode d'un objet qui n'existe pas - donc crash.


Que ce soit ordures collectées ou non, je ne suis pas sûr, mais la demande crée un démon Thread, donc vous ne devriez pas prendre soin que beaucoup (ne hésitez pas à découvrir). Il ya un comment à ce sujet, donc il n'est probablement pas recueilli encore.

Le UrlRequest dépend cependant fortement de Kivy et cela est visible here. Il utilise Kivy Clock. Cela signifie qu'à moins que l'application Kivy ne soit exécutée, la requête n'ira pas plus loin, c'est-à-dire qu'elle devrait s'arrêter à on this line. Essayez simplement d'ajouter print('something') au UrlRequest._dispatch_result() et vous verrez qu'il est complètement ignoré, car Kivy Clock ne fonctionne pas (donc la fonction n'est pas appelée).

Cependant, avec cet exemple, où l'application Kivy est exécutée, je n'y vois aucun problème.

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

En fait 'UrlRequest._dispatch_result()' est appelé. Et je n'appelle pas ce code sur un contexte d'application kivy. C'est la source si vous voulez voir. https://github.com/eteamin/Exmoore/blob/master/models/task.py et ceci est le fichier principal https://github.com/eteamin/Exmoore/blob/master/main.py – Juggernaut

+0

Je vois . Puis, dans [ce cas] (https://github.com/eteamin/Exmoore/blob/b01df0ce5bfab9d38849877f76e3e6e0b2127cab/main.py#L38) je crois que votre objet * 'DownloadTask' * est collecté. – KeyWeeUsr

+0

Aussi si je mets une fonction au lieu d'une méthode comme rappel, la fonction sera appelée – Juggernaut