Kivy UrlRequest被称为一个类 - 方法没有被执行?

时间:2016-09-22 13:38:52

标签: kivy urlrequest

尝试尝试并构建一个解决UrlRequest使用的类,以检查给定的URL是否有效。结果比预期的要困难一点!

问题是从未调用定义为类的一部分的on_success和on_failure / error方法。该脚本将抛出以下输出(基于打印命令):

http://www.google.com
request sent
URL doesn't work

现在我的怀疑是我从test_connection方法获得了返回码(“None”),而不是connectionSuccess或connectionFailure。如何让呼叫等待后者之一给出回报?欢迎任何建议。感谢。

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.network.urlrequest import UrlRequest

class WebExplorer():      
    def test_connection(self, path):
        self.path = path
        print (self.path)
        req = UrlRequest(self.path,on_failure=self.connectionFailure,on_error=self.connectionFailure,on_success=self.connectionSuccess)
        print ("request sent")

    def connectionSuccess(self,*args):
        print ("connectionSuccess")
        return 0

    def connectionFailure(self,*args):
        print ("connectionFailure")
        return 1


class MainScreen(FloatLayout):
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        self.address = 'http://www.google.com'

        if WebExplorer().test_connection(self.address) == 0:
            print ("URL works")
        else:
            print ("URL doesn't work")

class App(App):
    def build(self):
        return MainScreen()


if __name__ == "__main__": 
    App().run() 

更新2016-09-27 我改变了我的代码,我花了好几个小时试图弄清楚问题。首先是代码:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.network.urlrequest import UrlRequest

class WebExplorer():

    def test_connection(self, path):
        self.path = path
        req = UrlRequest(self.path,on_failure=self.connectionFailure,on_error=self.connectionFailure,on_success=self.connectionSuccess)
        req.wait()
        return (self._return_value)

    def connectionSuccess(self, req, results):
        print ("Success")
        self._return_value = [0,results]

    def connectionFailure(self, req, results):
        print ("Failure")
        self._return_value = [1,results]


class MainScreen(FloatLayout):
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        self.URLtest = ['http://www.ikea.com/','https://www.google.com','https://www.sdfwrgaeh.com']
        for URL in self.URLtest:
            self.returnCode = WebExplorer().test_connection(URL)
            if self.returnCode[0] == 0:
                print ("Correct URL")
            else:
                print ("Wrong URL")

class App(App):
    def build(self):
        return MainScreen()

if __name__ == "__main__": 
    App().run() 

为什么有3个网址?因为一个是“正确的”(宜家),一个是重定向(谷歌),一个是完全虚假的。事实证明,该代码仅适用于第一个。当结果是失败/错误时,req.wait不起作用(顺便说一句,我不知道这两者之间有什么区别)。

所以问题是如何使req.wait进程失败,或者如何使用正确的错误代码退出类。我认为Clock.schedule_interval定期检查状态,因为当URL不正确时甚至没有执行事件方法,我无处可设置我的变量-_-

1 个答案:

答案 0 :(得分:0)

UrlRequest是一个异步,这意味着在您的应用程序进行时,后台会处理实际请求。函数on_failure等是回调,即它们将在请求完成时被调用 - 但这意味着返回值是"丢失"。您获得的返回值确实来自test_connection函数。

您在邮件列表中提到要对根网址进行调用,对您收到的内容进行一些处理,然后根据内容和用户互动向郊区发出新请求。

以下内容应为您尝试执行的操作提供框架。

class WebExplorer

    def __init__(self, gui):
        self._visited_urls = [] # to prevent endless redirect loops
        self._visiting = set() # to check if we are still doing something
        self.gui = gui # used to display buttons in process_result

    def get_url(self, url):
        self._visited_urls.append(url)
        self._visiting.add(url)
        UrlRequest(url, 
            on_success=self.process_result,
            on_failure=self.failure,
            on_error=self.failure, # what is the difference between failure and error?
            on_redirect=self.redirect)

    def redirect(self, req):
        self._visiting.discard(req.url)
        self.get_url(req.req_headers["Location"]) # check if correct handling of 3xx

    def process_result(self, req):
        self._visiting.discard(req.url)
        #TODO process the body to extract urls you want to visit

        box = BoxLayout()
        for url in urls_you_want_to_visit:
            button = Button()
            button.text = url
            # I'm not sure if the following works due to some scoping oddities
            # if - no matter which button is pressed - the same url is called
            # this line is probably at fault
            button.bind(on_press=lambda: self.get_url(url)) 
            box.add_widget(button)

        gui.add_widget(box)

当然还有很多需要改进的地方。它也没有经过测试,因此它可能包含错误。