Python从使用线程到使用async/await的深入讲解

Python从使用线程到使用async/await的深入讲解

1. 线程

1.1 什么是线程?

线程是程序执行流的最小单元,是进程的一个执行单元。线程通过共享运行时环境,可以提高程序的并发性,线程有轻量级、及时性等特点。

1.2 Python的线程模块

Python的标准库threading提供了线程相关的模块,使用起来非常简单。

import threading

def worker():
    print('Thread %s is working' % threading.current_thread().getName())

t = threading.Thread(target=worker)
t.start()

上述代码中,使用threading.Thread类创建线程对象,使用start方法启动线程,使用current_thread方法获取当前线程对象,使用getName方法获取线程名。

1.3 线程的并发问题

虽然Python的线程机制非常易用,但是Python的线程是基于操作系统底层线程的,而不是真正的并发线程。因为Python的Global Interpreter Lock (GIL)机制,同一时刻只能有一个线程在执行Python代码,其他线程只能在等待GIL。所以使用线程并不能真正充分利用多核CPU,也无法真正实现多线程并发。因此,使用线程可能带来线程切换的开销而降低程序性能。

2. 协程

2.1 什么是协程?

协程是一种用户态的轻量级线程,也称为纤程 (Fiber),协程可以看作特殊的迭代器,可以由程序员控制运行状态,支持用户态调度,无线程切换开销。

2.2 Python的协程模块

Python 3.5开始加入async/await语法实现原生协程。使用协程需要用到Python的asyncio模块。

下面是一个使用async/await语法的协程示例:

import asyncio

async def worker():
    print('Coroutine is working')
    await asyncio.sleep(1)
    print('Coroutine is finished')

loop = asyncio.get_event_loop()
loop.run_until_complete(worker())

上述代码中,使用asyncawait定义协程,使用asyncio.sleep模拟协程执行任务,使用get_event_loop方法获取事件循环对象,使用run_until_complete方法运行协程。

2.3 协程和线程的区别

线程和协程都是并发机制,但是线程是基于操作系统底层线程的,因此他们的并发模型在底层上有很大的区别。协程通过用户态调度,对于大量I/O密集型操作的场景非常适用,但是对于CPU密集型操作的场景则不一定有优势,因为无法利用多核CPU。

3. 示例说明

3.1 线程示例

下面是一个使用线程池的示例,实现并发下载多张图片:

import requests
import threading
from concurrent.futures import ThreadPoolExecutor

def download(url, filename):
    print('Thread %s is downloading image: %s' % (threading.current_thread().getName(), url))
    resp = requests.get(url)
    with open(filename, 'wb') as f:
        f.write(resp.content)

urls = ['https://picsum.photos/200/200/?image=%d' % i for i in range(10)]
pool = ThreadPoolExecutor(max_workers=5)
for i, url in enumerate(urls):
    filename = 'image_%d.jpg' % i
    pool.submit(download, url, filename)

在该示例中,使用requests发送网络请求下载多张图片,使用ThreadPoolExecutor创建线程池,并通过submit方法向线程池中提交任务。由于线程是基于操作系统底层线程的,所以程序在执行过程中会有线程切换的开销。

3.2 协程示例

下面是一个使用协程的示例,实现并发下载多张图片:

import aiohttp
import asyncio

async def download(url, filename):
    print('Coroutine is downloading image: %s' % url)
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            with open(filename, 'wb') as f:
                f.write(await resp.content.read())

urls = ['https://picsum.photos/200/200/?image=%d' % i for i in range(10)]
tasks = [download(url, 'image_%d.jpg' % i) for i, url in enumerate(urls)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*tasks))

在该示例中,使用aiohttp发送异步网络请求下载多张图片,使用asyncio异步执行协程任务。由于协程是用户态调度,不需要线程切换的开销,可以提高程序的性能。

4. 总结

线程和协程都是并发编程的重要方式,但是在线程和协程之间需要根据实际需求进行选择。在大量I/O密集型操作的场景下,协程可以取得很好的效果,而在大量CPU密集型操作的场景下,则需要考虑使用多进程或大规模并行计算。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python从使用线程到使用async/await的深入讲解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Python 图形绘制详细代码(二)

    当涉及到Python的图形绘制时,Matplotlib通常是最流行的库。这个库能够创建各种类型的图表,如线图、散点图、饼图、直方图和更多。正如“Python 图形绘制详细代码(一)”中所示,Matplotlib api具有极其广泛和复杂的选项。 接下来,我们将进一步深入学习一些更高级的绘图技术。 让我们一起开始: 简单的子图 有时候,在单个图表中同时展示多个…

    python 2023年5月19日
    00
  • Python input()函数案例教程

    下面就是Python input()函数案例教程的完整攻略。 1. 什么是input()函数 input()函数是Python内置函数之一,用于从标准输入读取一行文本,并返回为字符串类型。通俗点说,就是可以获取用户在终端上的输入。 2. input()函数的基本使用 input()函数的基本语法格式如下: input([prompt]) 其中,可选参数pro…

    python 2023年6月5日
    00
  • 在Python中使用NumPy对切比雪夫级数进行积分并设置积分的下限

    首先,我们需要导入NumPy和SciPy库中的integrate模块用于积分。代码示例: import numpy as np from scipy import integrate 接着,我们需要定义切比雪夫级数。代码示例: def chebyshev_func(x, n): return np.cos(n * np.arccos(x)) 其中x为自变量,…

    python-answer 2023年3月25日
    00
  • Python urllib库如何添加headers过程解析

    当我们通过 Python 中的 urllib 库向某个网站发送 GET 或 POST 请求时,我们需要在请求头中添加一些自定义信息,例如 User-Agent,Cookies 等,以便对方服务器识别我们的身份或做一些其他限制。在 urllib 的 urllib.request 模块中,我们可以使用 Request 类来构造一个请求对象,并通过 add_hea…

    python 2023年6月3日
    00
  • 如何使用Python连接和操作PostgreSQL数据库?

    在Python中,可以使用psycopg2模块连接和操作PostgreSQL数据库。以下是Python使用psycopg2模块连接和操作PostgreSQL数据库的完整攻略,包括连接PostgreSQL数据库、插入数据、查询数据、更新数据和删除数据等操作。 连接PostgreSQL数据库 在Python中,可以使用psycopg2模块连接PostgreSQL…

    python 2023年5月12日
    00
  • Python结合Window计划任务监测邮件的示例代码

    下面是Python结合Windows计划任务监测邮件的示例代码攻略。 1. 需求分析 我们需要实现一个程序,定时检查某个文件夹内是否有新文件添加,并将新文件的名称和路径以邮件的形式通知用户。为了实现定时运行程序的功能,我们可以利用Windows系统自带的计划任务功能。 2. 实现方式 我们可以使用Python的第三方库watchdog来监控文件夹内的文件变化…

    python 2023年6月5日
    00
  • Python中的变量与常量

    以下是详细讲解“Python中的变量与常量”的完整攻略,包含两个示例说明。 1. 变量 在Python中,变量是用于储数据的标识符。变量可以存储不同类型的数据,例如整数、浮点数、字符串等。在Python中,变量的值随时更改。 以下是一个使用变量的示例: x = 5 y = "Hello, World!" print(x) print(y)…

    python 2023年5月14日
    00
  • Python3中的bytes和str类型详解

    Python3中的bytes和str类型详解 在Python3中,bytes和str类型都是用来存储数据的,但是它们之间有很大的区别。在这篇攻略中,我们将详细讲解bytes和str类型的不同之处,以及如何在它们之间进行转换。 1. str类型 str类型是Python3中最基本的字符串类型,用于存储Unicode编码的字符串。我们可以通过以下方式来创建一个s…

    python 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部