2013-05-17 70 views
3

我正在尋找一個方式做Perl的HTTP ::異步模塊的next_response方法的Python相當於Perl的HTTP :: Async-> next_response

的HTTP相當於::異步模塊不產卵任何背景的線程,也不使用任何回調。相反,每當有人(在我的情況下,主線程)調用對象的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實例,我我會採取所有我能得到的選擇(標準庫或其他部分),因爲我必須對它們進行評估,以確保它們可以在我的特定限制條件下運行。

回答

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。

你可以,但是你想,我只是粘貼一段代碼恰好是螺紋:)

一次嘗試另一個項目進行修改:

class EchoHandler(asyncore.dispatcher_with_send): 

    def handle_read(self): 
     data = self.recv(8192) 
     if data: 
      self.send(data) 
+0

謝謝,但正如我在說問題,嵌入環境的限制禁止我啓動新線程。 – Arnavion

+0

因此,刪除線程部分,這對我來說只是一個方便的事情。 – Torxed

+0

這是一個「你能做什麼」的答案,修改它,嘗試一下,並繞過。 – Torxed