3

我正在寻找一种与 Perl 的 HTTP::Async 模块的 next_response 方法等效的方法

HTTP::Async 模块不产生任何后台线程,也不使用任何回调。相反,每次任何人(在我的例子中,主线程)调用对象上的 next_response 时,操作系统到目前为止已接收到的所有数据都会被读取(阻塞,但瞬时,因为它只处理已经接收到的数据)。如果这是响应的结尾,则 next_response 返回一个 HTTP::Response 对象,否则返回 undef。

该模块的用法类似于(伪代码):

request = HTTP::Async(url)
do:
    response = request->next_response()
    if not response:
        sleep 5 # or process events or whatever
while not response

# Do things with response

据我所知,Python 的 urllib 或 http.client 不支持这种风格。至于我为什么要以这种风格来做:

  • 这适用于嵌入式 Python 环境,在该环境中我无法生成线程,也无法生成任何 Python。
  • 我仅限于单个线程,它实际上是嵌入应用程序的线程。这意味着我也不能有任何延迟的回调——应用程序决定何时让我的 Python 代码运行。我所能做的就是请求嵌入应用程序每 50 毫秒调用一次我选择的回调,比如说。

有没有办法在 Python 中做到这一点?

作为参考,这是我现在拥有的 Perl 代码示例,我希望将其移植到 Python:

httpAsync = HTTP::Async->new()

sub httpRequestAsync {
    my ($url, $callback) = @_; # $callback will be called with the response text

    $httpAsync->add(new HTTP::Request(GET => $url));

    # create_timer causes the embedding application to call the supplied callback every 50ms
    application::create_timer(50, sub {
        my $timer_result = application::keep_timer;
        my $response = $httpAsync->next_response;
        if ($response) {
            my $responseText = $response->decoded_content;
            if ($responseText) {
                $callback->($responseText);
            }
            $timer_result = application::remove_timer;
        }

        # Returning application::keep_timer will preserve the timer to be called again.
        # Returning application::remove_timer will remove the timer.
        return $timer_result;
    });
}

httpRequestAsync('http://www.example.com/', sub {
    my $responseText = $_[0];
    application::display($responseText);
});

编辑:鉴于这是一个嵌入式 Python 实例,我将采用我能得到的所有替代方案(标准库的一部分或其他),因为我必须评估所有这些以确保它们可以在我的特定环境下运行约束。

4

1 回答 1

0

注意:如果您只想在调用接收数据时检索数据,只需添加一个标志handle_receive并将其添加到内部的 sleep 块中,handle_receive从而仅在您调用函数时为您提供数据。

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import asyncore, errno
from socket import AF_INET, SOCK_STREAM
from time import sleep

class sender():
    def __init__(self, sock_send):
        self.s = sock_send
        self.bufferpos = 0
        self.buffer = {}
        self.alive = 1

    def send(self, what):
        self.buffer[len(self.buffer)] = what

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

    def run(self):
        while self.alive:
            if self.writable():
                logout = str([self.buffer[self.bufferpos]])
                self.s(self.buffer[self.bufferpos])
                self.bufferpos += 1
            sleep(0.01)

class SOCK(asyncore.dispatcher):
    def __init__(self, _s=None, config=None):
        self.conf = config
        Thread.__init__(self)

        self._s = _s

        self.inbuffer = ''
        #self.buffer = ''
        self.lockedbuffer = False
        self.is_writable = False

        self.autounlockAccounts = {}

        if _s:
            asyncore.dispatcher.__init__(self, _s)
            self.sender = sender(self.send)

        else:
            asyncore.dispatcher.__init__(self)
            self.create_socket(AF_INET, SOCK_STREAM)
            #if self.allow_reuse_address:
            #   self.set_resue_addr()

            self.bind((self.conf['SERVER'], self.conf['PORT']))
            self.listen(5)

            self.sender = None

        self.start()

    def parse(self):
        self.lockedbuffer = True

        ## Parse here
        print self.inbuffer

        self.inbuffer = ''
        self.lockedbuffer = False

    def readable(self):
        return True
    def handle_connect(self):
        pass
    def handle_accept(self):
        (conn_sock, client_address) = self.accept()
        if self.verify_request(conn_sock, client_address):
            self.process_request(conn_sock, client_address)
    def process_request(self, sock, addr):
        x = SOCK(sock, config={'PARSER' : self.conf['PARSER'], 'ADDR' : addr[0], 'NAME' : 'CORE_SUB_SOCK_('+str(addr[0]) + ')'})
    def verify_request(self, conn_sock, client_address):
        return True
    def handle_close(self):
        self.close()
            if self.sender:
                self.sender.alive = False
    def handle_read(self):
        data = self.recv(8192)
        while self.lockedbuffer:
            sleep(0.01)
        self.inbuffer += data
    def writable(self):
        return True
    def handle_write(self):
        pass

    def run(self):
            if not self._s:
            asyncore.loop()

imap = SOCK(config={'SERVER' : '', 'PORT' : 6668})
imap.run()

while 1
    sleep(1)

类似的东西?当有数据要接收时,始终附加到 inbuffer 的异步套接字。

你可以随心所欲地修改它,我只是从另一个项目中粘贴了一段代码,恰好是线程:)

最后一次尝试:

class EchoHandler(asyncore.dispatcher_with_send):

    def handle_read(self):
        data = self.recv(8192)
        if data:
            self.send(data)
于 2013-05-17T07:03:15.067 回答