【问题标题】:Kivy UrlRequest called as a class - Methods not executed?Kivy UrlRequest 作为一个类调用 - 方法未执行?
【发布时间】:2016-09-30 19:36:23
【问题描述】:

尝试尝试并构建一个解决使用 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 不正确时甚至不执行事件方法,所以我无处设置变量-_-

【问题讨论】:

    标签: kivy urlrequest


    【解决方案1】:

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

    您在邮件列表中提到要调用根 URL,对返回的内容进行一些处理,然后根据内容和用户交互向子 URL 发出新请求。

    以下内容应该为您正在尝试做的事情提供一个框架。

    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)
    

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

    【讨论】:

    • 感谢您的宝贵时间以及使用 req.wait() 的建议。但是,它仍然返回“无”,就像我没有输入代码一样。我按照您的建议应用了更改,并在“返回自我”之前添加了一个“打印(“返回值”,self._return_value)” ._return_value”的 test_connection 方法。它确实返回“无”
    • (无法添加到我之前的评论)。我还尝试在 req.wait() 之后放置一个睡眠命令。它仍然返回“无”。 wait() 的文档是进程返回到主线程“这个方法打算在主线程中使用,回调将从你调用的同一个线程分派。”,所以理论上没有理由不调用 on_success 方法,因此相应地设置返回码。错误?
    • 什么是req.result
    • 嗯,我不认为脚本使用了名为“req.result”的东西?什么意思?
    • 对不起,我的意思是“req.resultwait 调用之后的值是多少”。 req.result 应该表明请求是否成功。也许你得到了一个重定向,而 on_error 和 on_success 都没有被调用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多