Asyncore module usage example tutorial for Python learning

  • 2020-04-02 14:12:57
  • OfStack

This article analyzes the principle and usage of asyncore module in Python with an example, and shares it with you for your reference. Specific analysis is as follows:

The asyncore library is a standard python library that is a wrapper around an asynchronous socket. We can directly use the socket and other low-level libraries when operating the network, but asyncore makes it more convenient for us to operate the network and avoid the complexity of directly using socket, select, poll and other tools.

The library is simple and contains a function and a class
* loop () function
* the dispatcher base class
It is important to note that the loop function is global and not the dispatcher method

Each object inherited from the dispatcher class can be thought of as a socket that we need to work with, which can be a TCP connection or UDP, or even something else that is not commonly used. Easy to use, we need to define a class that inherits the dispatcher, and then we can override (override) some methods.

The methods we need to override generally begin with handle_.


class refuse(dispatcher):
  def handle_accept():
    #do nothing ...
    pass

The loop() function detects a dict that holds an instance of dispatcher, a dictionary called a channel. Each time a dispatcher object is created, it adds itself to a default dict (or, of course, the channel itself). When an object is added to a channel, the behavior of the socket is defined, the program only needs to call loop(), and everything is done.

Asyncore is a good design in the python standard library
In the standard documentation for python, there is an example of asyncore


import asyncore, socket
class http_client(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.0rnrn' % 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:]
c = http_client('www.python.org', '/')
asyncore.loop()

Run this function and find that the home page of python.org is downloaded, which means that we implement an HTTP layer protocol? But we only use socket level API... So let's take a look at these lines of code!

Writable and readable are called when a socket is detected to be writable or when data is detected to arrive, and a bool is returned to determine whether to handle_read or handle_write

Turning asyncore.py on shows that the methods writable and readable defined in the dispatcher class are fairly simple:


def readable(self):
  return True
def writable(self):
  return True

That is, once a read or write is detected, handle_read/handle_write is called directly, but in the above example, we see an overload (which looks like a C++ virtual function, doesn't it?).


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

Obviously, we only return True to the writable caller when we have data to send, so that we don't need to make any more judgments in handle_write.

The rest of the code looks pretty clear, with a sense of force. When an HTTP server sends and processes your request, close the socket, our handle_close() does its job. Close () removes the object itself from the channel and is responsible for destroying the socket object.


def close(self):
  self.del_channel()
  self.socket.close()

The loop() function detects an empty channel, exits the loop, the program completes, and exits.

I hope this article has helped you with your Python programming.


Related articles: