我正在寻找一种方法来做相当于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中执行此操作?
作为参考,这是我现在拥有的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实例,我将采取我可以获得的所有替代方案(标准库的一部分或其他方式),因为我必须评估所有这些以确保它们可以运行在我特别的限制下。
答案 0 :(得分:0)
注意:如果您只想在收到要接收的数据时检索数据,只需向handle_receive
添加一个标志,然后将其添加到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)
有什么想法吗? 当有数据要接收时,Asyncore套接字总是附加到inbuffer。
你可以根据需要修改它,我只是粘贴了另一个碰巧是Threaded的项目中的一段代码:)
上次尝试:
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(8192)
if data:
self.send(data)