Python and coroutine from Python2-Python3

Personal blog navigation page (clickRightlinkTo open the personal blog):Daniel takes you to the technology stack 

Coroutine, also known as micro-thread, fiber, English name Coroutine; in one sentence, what is a thread: Coroutine is a lightweight thread in user mode.

Python's support for coroutines is relatively simple in python2, but there are also third-party libraries that can be used. Fully supported in python3 has also become a core function of python3, which is worth learning.

 

Coroutine introduction

Coroutine, also known as micro-thread, fiber, English name Coroutine; in one sentence, what is a thread: Coroutine is a lightweight thread in user mode.

The coroutine has its own register context and stack. When the coroutine scheduling switch, save the register context and stack to other places, and restore the previously saved register context and stack when switching back. Therefore: the coroutine can retain the state of the last call (that is, a specific combination of all local states). Each time the process is reentered, it is equivalent to entering the state of the last call. The location of the logic flow.

Advantages of coroutine:

1) No overhead of thread context switching

2) No need for atomic operation locking and synchronization overhead

3) Convenient to switch control flow and simplify programming model

4) High concurrency + high scalability + low cost: it is not a problem for a CPU to support tens of thousands of coroutines. So it is very suitable for high concurrency processing.

Disadvantages of coroutine:

1) Unable to use multi-core resources: the essence of the coroutine is a single thread, it cannot use multiple cores of a single CPU at the same time, the coroutine needs to cooperate with the process to run on multiple CPUs

2) Blocking operations (such as IO) will block the entire program

 

Coroutines in Python2

yield keyword

Python2's support for coroutines is achieved through the yield keyword. The following sample code is a common producer-consumer model. The code example is as follows:


def consumer():

    r = ''

    while True:

        n = yield r

        if not n:

            continue

        print('[CONSUMER] Consuming %s...' % n)

        r = '200 OK'



def produce(c):

    c.next()

    n = 0

    while n < 5:

        n = n + 1

        print('[PRODUCER] Producing %s...' % n)

        r = c.send(n)

        print('[PRODUCER] Consumer return: %s' % r)

    c.close()



if __name__ == '__main__':

    c = consumer()

    produce(c)

Results of the:

Note that the consumer function is a generator. After passing a consumer to produce:

1) First call c.next() to start the generator;

2) Then, once something is produced, switch to consumer execution via c.send(n);

3) The consumer gets the message through yield, processes it, and sends the result back through yield;

4) Produce gets the result processed by the consumer and continues to produce the next message;

5) Produce decides not to produce, close the consumer through c.close(), and the whole process ends.

The whole process is lock-free and executed by one thread. Produce and consumer cooperate to complete the task, so it is called "coroutine" instead of thread preemptive multitasking.

The traditional producer-consumer model is that one thread writes messages, one thread fetches messages, and controls the queue and waiting through the lock mechanism, but it may deadlock if you are not careful.

If you switch to a coroutine, after the producer produces the message, it directly jumps to the consumer through yield to start execution, and after the consumer finishes executing, it switches back to the producer to continue production, which is extremely efficient.

Python's support for coroutines is still very limited, and the yield used in generators can implement coroutines to a certain extent. Although the support is not complete, it can already exert considerable power.

 

gevent module

Python provides basic support for coroutines through yield, but it is not complete. The third-party gevent provides relatively complete coroutine support for Python. gevent is a third-party library that implements a coroutine through greenlet. The basic idea is:

When a greenlet encounters an IO operation, such as accessing the network, it automatically switches to other greenlets, waits until the IO operation is completed, and then switches back to continue execution when appropriate. Because the IO operation is very time-consuming, the program is often in a waiting state, and gevent automatically switches the coroutine for us, ensuring that there are always greenlets running instead of waiting for IO. Since the switch is automatically completed during IO operations, gevent needs to modify some standard libraries that come with Python. This process is completed through monkey patch at startup.

The sample code is as follows:


from gevent import monkey; monkey.patch_all()

import gevent

import urllib2



def f(url):

    print('GET: %s' % url)

    resp = urllib2.urlopen(url)

    data = resp.read()

    print('%d bytes received from %s.' % (len(data), url))



gevent.joinall([

        gevent.spawn(f, 'https://www.python.org/'),

        gevent.spawn(f, 'https://www.yahoo.com/'),

        gevent.spawn(f, 'https://github.com/'),

])

Results of the:

As can be seen from the execution results, the order of website visits is automatically switched.

 

gevent advantages and disadvantages

Using gevent, you can obtain extremely high concurrency performance, but gevent can only run under Unix/Linux, and normal installation and operation are not guaranteed under Windows. Python founder Gvanrossum has never liked Gevent, but prefers to implement asyncio (asynchronous implementation in python3) in another way.

1) Monkey-patching. The Chinese "monkey patch" is often used to hack the test environment. Gvanrossum said to use it as "patch-and-pray". Because Gevent directly modifies most of the blocking system calls in the standard library, including modules such as socket, ssl, threading, and select, it becomes a cooperative operation. However, there is no guarantee that the use of these standard libraries in a complex production environment will cause strange problems due to patching, so we can only pray.

2) Secondly, it was clearly stated in the Zen of Python: "Explicit is better than implicit." The monkey patch clearly deviates from this principle.

3) Third-party library support. You have to ensure that other network libraries used in the project must also use pure Python or explicitly support Gevent, and even if there is such a third-party library, you need to worry about the code quality and functionality of this third-party library.

4) Greenlet does not support Jython and IronPython, so gevent cannot be designed as a standard library.

There was no choice before. Many people chose Gevent, but now it is clear that there is a more orthodox and correct choice: asyncio (introduced in the next section). So I suggest you learn about Gevent and embrace asyncio.

In addition, if you know that using Gevent now and in the future will not cause trouble to the project, then it is also possible to use Gevent.

 

Coroutines in Python3

Gvanrossum hopes to implement a native generator-based coroutine library in Python 3 with direct built-in support for asynchronous IO. This is asyncio, which was introduced into the standard library in Python 3.4.

The following will briefly introduce the use of asyncio:

1) event_loop: The program opens an infinite loop, and the programmer will register some functions on the event loop. When a satisfying event occurs, the corresponding coroutine function is called.

2) coroutine coroutine: coroutine object, refers to a function defined using the async keyword, its call will not immediately execute the function, but will return a coroutine object. The coroutine object needs to be registered in the event loop and called by the event loop.

3) task task: A coroutine object is a function that can be suspended natively, and the task is to further encapsulate the coroutine, which contains various states of the task.

4) Future: represents the result of tasks that will be executed or not executed in the future. There is no essential difference between it and task

5) async/await keywords: python3.5 is used to define keywords for coroutines, async defines a coroutine, and await is used to suspend blocking asynchronous call interfaces.

The code example is as follows:


import asyncio

import time



now = lambda: time.time()

async def do_some_work(x):

    print('Waiting: {}s'.format(x))



    await asyncio.sleep(x)

    return 'Done after {}s'.format(x)



async def main():

    coroutine1 = do_some_work(1)

    coroutine2 = do_some_work(5)

    coroutine3 = do_some_work(3)



    tasks = [

        asyncio.ensure_future(coroutine1),

        asyncio.ensure_future(coroutine2),

        asyncio.ensure_future(coroutine3)

    ]

    done, pending = await asyncio.wait(tasks)

    for task in done:

        print('Task ret: ', task.result())



start = now()



loop = asyncio.get_event_loop()

task = asyncio.ensure_future(main())

try:

    loop.run_until_complete(task)

    print('TIME: ', now() - start)

except KeyboardInterrupt as e:

    print(asyncio.Task.all_tasks())

    print(asyncio.gather(*asyncio.Task.all_tasks()).cancel())

    loop.stop()

    loop.run_forever()

finally:

    loop.close()

Results of the:

It can be seen that the program execution time is the one with the longest waiting time.

 

Use async to define coroutine objects, and use await to suspend time-consuming operations. Just like yield in the generator, the function gives up control. When the coroutine encounters await, the event loop will suspend the coroutine and execute other coroutines until the other coroutines are also suspended or executed, and then the next coroutine is executed. Time-consuming operations are generally some IO operations, such as network requests, file reading, etc. We use the asyncio.sleep function to simulate IO operations. The purpose of the coroutine is to make these IO operations asynchronous.

 

Asyncio is a powerful built-in library in python3. The above is just a brief introduction to the usage of asyncio. If you are interested, it is worth learning!

Attached with Java/C/C++/Machine Learning/Algorithm and Data Structure/Front End/Android/Python/Programmer Must Read/Book List:

(Click on the right to open the personal blog with dry goods):Technical dry goods store
=====>>①【Java big cow takes you entry to advanced road】<<====
=====>>②【Algorithm data structure + acm big cow takes you to the advanced road】<<===
=====>>③[Database big cow takes you to the entry to the advanced road]<<=====
=====>>④[Web front-end big cow takes you entry to advanced road]<<====
=====>>⑤【Machine learning and python will take you to the advanced road】<<====
=====>>⑥【The architect takes you to the advanced road】<<=====
=====>>⑦[C++ Da Niu takes you to the advanced road]<<====
=====>>⑧[ios Daniel takes you to the advanced road]<<====
=====>>⑨[Web security expert takes you to the advanced road]<<=====
=====>>⑩[Linux and operating system big cows will take you to the advanced road]<<=====

There is no fruit for nothing in the world. I hope that all young friends and friends who want to learn technology will overcome all obstacles on the road of determined to enter the road of technology. It will bring you a dream in your life, your work, and your future.

Intelligent Recommendation

[Python] python2 turn python3

Sometimes we perform scripts in a python3 environment, which is found to be written by Python2 syntax, causing problems, in which case we don't have to modify syntax one by one, but you can use Python...

[Python] code migration tool from python2 to python3: 2to3.py

Code migration tool from python2 to python3: 2to3.py There are many gaps in the syntax of python3.x and python2.x code, the official python provides us with a convenient migration solution: 2to3.py 1....

Change the default python command from python2 to python3 under Linux

method one: Convert commands from bash, python to python3. The restart may fail. 1. Write data to .bashrc file echo alias python=python3 >> ~/.bashrc 2. Make the environment variables effective ...

Solve Ubuntu Default Python from Python3 to Python2 (Visual Method)

Solve Ubuntu Default Python from Python3 to Python2 (Visual Method) author: [email protected] version: 1.0 time: 05/25/2021 Problem Description Ubuntu 20.04 The default Python version is 3.8.5, yo...

The CENTOS system changed the default version of Python from Python2 to Python3

Python2 to Python3 principle step Environment variable detailed explanation principle 1. Install Python3 and add python3 to the environment variable. 2. Because Yum is compatible with python2, it is n...

More Recommendation

Web crawler: from python2 to python3

A long time ago, when I was in Python 2, I simply got a little crawler. Later, after 3, I found that many of the previous programs were not available. The most basic page capture would not work, and I...

Python3 and Python2 are different from the use

Python 3 can use super (). Xxx instead of super (class, self) .xxx; If Python 2 is used, the super () of this article needs to be replaced with Super (Class, Self). . What is the role of Super? The fo...

Python2 is different from Python3, turn Python3 code

table of Contents First, Python2 and Python3 coexistence in Windows Second, Python2 and Python3 code change points 1. Python2 and Python3's Print function is different 2. Python3 Dict is not .has_key....

Python: with 2to3 Python2 turn Python3

Python2 inprintIt is a statement, and is a function Python3 Python2 Codeexample.py Command line execution instruction Python3 Code Writing code compatible reference: https://docs.python.org/2/library/...

Self Python - python2 and python3 codec

In Python2Compile and installWhen the parameters can be --enable-unicode = ucs2 or --enable-unicode = ucs4 are designated uses 2 bytes or 4 bytes, a unicode character, use 4 bytes to python3 a default...

Copyright  DMCA © 2018-2026 - All Rights Reserved - www.programmersought.com  User Notice

Top