SoFunction
Updated on 2024-11-17

Python 3.10 Generator Generator Coroutine Native Concurrency Explained

introductory

Generally speaking, a generator is a special kind of iterator that allows a function to pause during execution and retain its state when execution resumes. Concurrency, on the other hand, allows a function to pause during execution and retain its state when execution resumes. In Python 3.10, the means of implementation of native concurrency, is the generator, or to be more specific: a concurrency is a special kind of generator, and a generator, the introductory concurrency of the mind.

The underlying implementation of the concatenation

We know that Python 3.10 can use the async and await keywords to achieve the definition and scheduling of native concurrent functions, but in fact, we can also use generators to achieve the effect of concurrent, generator functions and ordinary functions is the difference is that the generator function uses the yield statement to pause the execution and return the result. For example, the following is a simple concurrent program using a generator function:

def my_coroutine():  
    while True:  
        x = yield  
        print(x)  
# Create a co-program using a generator function
coroutine = my_coroutine()  
# Launching a concurrent program
next(coroutine)  
# Passing data in the concurrent program
(1)  
(2)  
(3)

The program returns:

➜  mydemo git:(master) ✗ /opt/homebrew/bin/python3.10 "/Users/liuyue/wodfan/work/mydemo/src/"  
1  
2  
3

In the code above, the generator function my_coroutine uses an infinite loop to implement the logic of the concatenation. Whenever the send method is called, the coroutine resumes execution at the yield statement and assigns the incoming argument to the variable x. The coroutine is then executed.

This completes the workflow pattern of Concurrent Execution -> Blocking -> Switching -> Callbacks.

Of course, as an event loop mechanism, the concatenation service startup may run indefinitely, and to close the concatenation service, you can use the close() method of the generator. When a concurrent program is closed, it generates the GeneratorExit exception, which can be caught using the generator:

def my_coroutine():  
    try :  
        while True:  
            x = yield  
            print(x)  
    except GeneratorExit:  
            print("Concurrent shutdown")  
# Create a co-program using a generator function
coroutine = my_coroutine()  
# Launching a concurrent program
next(coroutine)  
# Passing data in the concurrent program
(1)  
(2)  
(3)  
()

The program returns:

➜  mydemo git:(master) ✗ /opt/homebrew/bin/python3.10 "/Users/liuyue/wodfan/work/mydemo/src/"  
1  
2  
3  
Collaboration shutdown

business scenario

In actual business scenarios, we can also use the generator to simulate the co-processing process, mainly in the IO flow of data operations, assuming that we need to transfer data from the local to the server, the first to establish the link object:

class Connection:  
    def __init__(self, addr):  
         = addr  
    def transmit(self, data):  
        print(f"X: {data[0]}, Y: {data[1]} sent to {}")

The generator function is then created:

def send_to_server(conn):  
    while True:  
        try:  
            raw_data = yield  
            raw_data = raw_data.split(' ')  
            coords = (float(raw_data[0]), float(raw_data[1]))  
            (coords)  
        except ConnectionError:  
            print("Link lost, making callbacks.")  
            conn = Connection("Reconnect.")

The simulated transfer of data is performed using the generator to call the transmit method of the link class, and if the link is broken, a callback is triggered to reconnect and execute the logic:

if __name__ == '__main__':  
    conn = Connection("")  
    sender = send_to_server(conn)  
    (None)  
    for i in range(1, 6):  
        (f"{100/i} {200/i}")  
    # Simulate a broken link
     = None  
    (ConnectionError)   
    for i in range(1, 6):  
        (f"{100/i} {200/i}")

The program returns:

X: 100.0, Y: 200.0 sent to   
X: 50.0, Y: 100.0 sent to   
X: 33.333333333333336, Y: 66.66666666666667 sent to   
X: 25.0, Y: 50.0 sent to   
X: 20.0, Y: 40.0 sent to   
Link lost,carry out a callback  
X: 100.0, Y: 200.0 sent to reconnect  
X: 50.0, Y: 100.0 sent to reconnect  
X: 33.333333333333336, Y: 66.66666666666667 sent to reconnect  
X: 25.0, Y: 50.0 sent to reconnect  
X: 20.0, Y: 40.0 sent to reconnect

In this way, we can utilize the generator's "state retention" mechanism to control the callback remedies for sudden network link disconnections.

So a concurrent program is a special kind of generator:

async def test():  
    pass  
print(type(test())) 

And guess what?

<class 'coroutine'>

concluding remarks

Admittedly, generators and concatenations are not exactly the same concept; unlike generators, concatenations can be resumed for execution by another function (called the caller), rather than only by the generator itself. This allows concatenations to be used to implement more complex control flows, as they can be suspended during execution and resumed at any point.

The above is Python3.10 Generator Generator Coroutine native concatenation details, more information about Python Generator native concatenation please focus on my other related articles!