current position:Home>Event loop of Python collaboration series

Event loop of Python collaboration series

2022-01-29 21:49:25 cxapython

Little knowledge , Great challenge ! This article is participating in “ A programmer must have a little knowledge ” Creative activities .

The event loop

An event is a message sent by a part of a program under certain conditions , A loop is a construct that completes and executes a program under certain conditions until it is completed , therefore , An event loop is a loop , It allows users to subscribe to event transfers and register handlers / Callback . It enables programs to run asynchronously . The event loop delegates all the events it receives to their respective callbacks , Most implementations of callback patterns have a major drawback , They define the programming style by introducing a lot of nesting . therefore , To show that some parts of the program depend on each other , We use sorting , However , In the case of relying on asynchronous results , The following pattern appears :

  • Nested callbacks , So that internal callbacks can access the results of external callbacks ( Closure )
  • Use objects that act as proxies for future results ( So-called Future or Promise )
  • coroutines , It is a suspended function that runs in an event loop

Nesting Callback( Nested callbacks )

The rule of thumb for nested callbacks is , If you need to wait for the result of the callback , You must embed the code into the corresponding callback . You will soon fall into the infamous hellish situation of callback . Callback hell is the depth of callback nesting , This makes the reasoning and improvement of the program a nightmare .


Futures/Promises Is an object that encapsulates the results of asynchronous calls and error handling . They will eventually provide APIs To query results/exceptions Current state , And register callbacks to handle results/exceptions Methods . Because they encapsulate the future context of asynchronous calls and need to be nested , Therefore, the generated program seems to be written in a more top-down way .(.then That form )


You can simply understand a coroutine as a function that can be interrupted . Pausing means that we can pause the coroutine anywhere in the function . This means that it must have some kind of atomic unit . That's what we're talking about tick, That's what we measured tick.tick Is the time unit of the event cycle , It contains all the actions that occur in an iterative step of the event loop

Collaborative processes can actually do more : They can pause themselves and wait for the result of another collaborative program . waiiting All logic of is coordinated by the event loop , Because it knows the corresponding co process state

Asyncio The life cycle of the event cycle in

asyncio The event loop in has four states : 1.Idle 2.Running 3.Stopped 4.Closed You can interact with the lifecycle of an event loop through four event loop methods , These methods can be divided into startup , Stop and close methods . They form the event cycle life cycle interface , all asyncio / Third party event loops need to provide compatibility .

1.run_forever 2.run_until_complete

call run_forever Method without parameters , and run_until_complete Method needs to pass in a coprocessor function as a parameter . To stop , We can use stop Method ; To shut down , We use close Method .

The Idle State( Idle state )

Idle state is the state in which the loop is created . In this state, no coprocessor or callback function is consumed . In this state loop.is_running return False.

The Running State( Running state )

The running state is calling loop.run_forever or loop.run_until_complete Then the state of the loop . In this state loop.is_running return True. The difference between these methods is , stay loop.run_until_complete Under the circumstances ,loop.run_until_complete The process will be packaged in asyncio.Future in . The callback is asyncio.Future Object as a handler , This object runs after consuming the coroutine completely loop.stop Method .

The Stopped State( Stop state )

The stop state is to call stop The state of the loop after the command . call stop After the method , call is_running Method does not return False, Consume all pending callbacks first . Only after they are consumed , The loop will enter the idle state .

The Closed State( The closed position )

Loop by calling close Method enters the closed state . Only when the cycle is not running , To call it .

Basic classes of event loops

stay Python 3 Two event loops are provided by default in . The abstract event loop class consists of and asyncio.base_events Module supply . AbstractEventLoop and BaseEventLoop Represents two potential classes for the implementation of an event loop .


AbstractEventLoop Class defines the native asyncio Interface of event loop in . Interface methods can be roughly divided into the following parts

  • Life cycle approach ( function 、 stop it 、 Query status and close loop )
  • Scheduling method
  • Callback
  • coroutines
  • establish Future object
  • Thread related methods
  • IO Operation related methods
  • Lower level API(socket, pipe, and reader/writer APIs)
  • High level APIs(server, pipe, and subprocess-related methods)
  • Signal method
  • Debugging mark management method

The API is stable , In the case of manual event loop implementation, it can be subclassed


Although based on higher-level components , But you should not use BaseEventLoop Class to create a manual loop implementation , Because of its API unstable . But it can be used as a guide to how to implement the interface . its BaseEventLoop._run_once Method in each of the loops tick On the call , Therefore, it includes all the operations required for one iteration . This will call all currently prepared callbacks ,I/O polling , Callback generated by scheduling , Then schedule call_later Callback , If you plan to implement the event loop yourself , You need to provide a similar method , The name and body of the function are just implementation details .

Are event loops operating system specific ?

Yes , Loop specific events are system specific This may affect API Availability and the speed of the event cycle . for example ,add_signal_handler and remove_signal_handler Yes, only UNIX The cycle of API. In addition to the lack of the corresponding native binding , One of the reasons behind the operating system characteristics is that most loops are based on selectors Modular implemented .selectors Is based on select Advanced of module improvement I/O Multiplexing interface . selectors Module built on Select, poll, devpoll, epoll, or kqueue above , It depends on the underlying operating system .selectors The module in the module is responsible for setting the default selector , The default selector is used by asynchronous modules .

if 'KqueueSelector' in globals():
   DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
   DefaultSelector = EpollSelector
elif 'DevpollSelector' in globals():
   DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
   DefaultSelector = PollSelector
  DefaultSelector = SelectSelector
 Copy code 

Pay attention to Windows There is another one based on I/O Complete port or short IoCP Of ProactorEventLoop Class implementation IOCP Official documents describe them as “ An efficient threading model for processing multiple asynchronous I / O requests on multiprocessor systems ”. for example , If needed asyncio Subprocesses API, Can be in Windows Upper use ProactorEventLoop.

The original text comes from my Zhihu column

copyright notice
author[cxapython],Please bring the original link to reprint, thank you.

Random recommended