用asyncore阅读网站

时间:2009-09-02 12:39:25

标签: python web-services sockets

我想异步读一个网站,据我所知,urllib是不可能的。现在我尝试用普通套接字阅读,但HTTP给了我地狱。 我遇到了所有类似的时髦编码,例如transfer-encoding:chunked,必须手动解析所有这些东西,我觉得编码C,而不是python。

不是像URLLib那样有一种更好的方式,异步吗?我真的不想重新实现整个HTTP规范,而是之前已经完成了。

扭曲当前不是一个选项。

问候,

汤姆

4 个答案:

答案 0 :(得分:7)

您可以自己实现异步调用。对于每个调用,启动一个新线程(或尝试从池中获取一个)并使用回调来处理它。

你可以用装饰师很好地完成这个任务:

def threaded(callback=lambda *args, **kwargs: None, daemonic=False):
    """Decorate  a function to run in its own thread and report the result
    by calling callback with it."""
    def innerDecorator(func):
        def inner(*args, **kwargs):
            target = lambda: callback(func(*args, **kwargs))
            t = threading.Thread(target=target)
            t.setDaemon(daemonic)
            t.start()
        return inner
    return innerDecorator

@threaded()
def get_webpage(url):
    data = urllib.urlopen(url).read()
    print data

答案 1 :(得分:5)

你看过http://asynchttp.sourceforge.net/了吗?

“Python的异步HTTP客户端”

'asynchttp''模块是Python库'asynchat'模块的逻辑扩展,它基于'asyncore'和'select'模块构建。我们的目标是提供优秀的'httplib'模块的功能,而不使用阻塞套接字。“

该项目的最后一次提交是2001-05-29,所以它看起来已经死了。但无论如何它可能会引起人们的兴趣。

免责声明:我自己没有使用它。

此外,this blog post提供了有关异步HTTP的一些信息。

答案 2 :(得分:1)

我来的最远的是使用修改后的asynchttp,这个代码建议。我试图使用asyncore / asynchat和asynchttp,带来很多痛苦。我花了很长时间才试图解决其中的所有错误(有一个方法handle_read,几乎从asyncore复制,只是非常缩进,并且让我头痛并使用分块编码)。另外,asyncore和asynchat最好不要根据谷歌上的一些提示使用。

我已经解决了扭曲,但这对你来说显然是不可能的。

它可能还取决于你想要对你的应用程序做什么以及为什么你想要异步请求,如果线程是一个选项,如果你正在进行GUI编程或其他什么,所以如果你可以减少更多的信息,那总是好的。如果没有,我会投票给上面建议的线程版本,它提供了更多的可读性和可维护性。

答案 3 :(得分:1)

Asyncore简单的HTTP客户端示例非常简单:)

http://docs.python.org/library/asyncore.html

import asyncore, socket

class HTTPClient(asyncore.dispatcher):

    def __init__(self, host, path):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect( (host, 80) )
        self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path

    def handle_connect(self):
        pass

    def handle_close(self):
        self.close()

    def handle_read(self):
        print self.recv(8192)

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]


client = HTTPClient('www.python.org', '/')
asyncore.loop()