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

yizhihongxing

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日

相关文章

  • windows系统中python使用rar命令压缩多个文件夹示例

    当在windows系统中使用Python操作系统文件时,常常需要压缩多个文件夹为一个压缩包。在Windows系统中,我们可以使用RAR命令来完成这一任务。 以下是使用RAR命令压缩多个文件夹的完整攻略: 步骤一:安装RAR命令行工具 我们需要先安装RAR命令行工具才能在Python脚本中调用RAR命令。可以从RARLab的官网下载这个工具。下载地址为:htt…

    python 2023年6月3日
    00
  • Python实现对字符串中字符提取校验

    以下是“Python实现对字符串中字符提取校验”的完整攻略: 一、问题描述 在Python中,我们经常需要对字符串进行处理,包括字符提取和校验等操作。本文将详细讲解Python中如何实现对字符串中字符提取校验的操作,并提供两个示例说明。 二、解决方案 2.1 字符提取 在Python中,我们可以使用字符串的下标来提取指定位置的字符。字符串的下标从0开始,可以…

    python 2023年5月14日
    00
  • 详解Python在列表,字典,集合中根据条件筛选数据

    我会为你详细讲解Python在列表、字典、集合中根据条件筛选数据的方法。 列表中筛选数据 在Python列表中,可以使用列表解析式,通过条件判断筛选数据。列表解析式的语法如下: [expression for item in iterable if condition] 其中,expression 为表达式,item 为可迭代对象的元素,iterable 为…

    python-answer 2023年3月25日
    00
  • python 在threading中如何处理主进程和子线程的关系

    来讲一下“python 在threading中如何处理主进程和子线程的关系”的完整攻略。 1. 使用 threading 模块创建子线程 在 Python 中使用 threading 模块创建子线程非常简单。代码如下: import threading def worker(): print("子线程执行中") t = threading…

    python 2023年5月19日
    00
  • 执行Django数据迁移时报 1091错误及解决方法

    一、背景介绍 在进行Django项目开发时,经常会使用到数据迁移(migration)功能,它能够方便地将模型中的数据结构更改同步到数据库。但有时在进行数据迁移时,会遇到错误反馈,比如报1091错误。本文将详细讲解这种错误的原因和解决方法。 二、错误原因 1091错误的报错信息为: django.db.utils.OperationalError: (109…

    python 2023年5月13日
    00
  • python字符串切片及常用方法示例详解

    Python的字符串是一种非常重要的数据类型,经常在我们的开发中使用。对于字符串的切片和各种常用方法,失误是我们必须要掌握的。 Python字符串切片 字符串切片是指对字符串进行裁剪,获取其一部分的操作,Python中字符串的切片使用切片运算符[ ],语法格式为: str[start:end:step] 其中: str:表示要进行切片操作的字符串。 star…

    python 2023年6月5日
    00
  • 详解如何利用tushare、pycharm和excel三者结合进行股票分析

    下面是详解如何利用tushare、pycharm和excel三者结合进行股票分析的完整实例教程。 一、前期准备 安装和配置 安装pycharm和tushare: 首先要安装好pycharm和tushare两个软件。pycharm是一款Python集成开发环境,tushare是一款用于获取股票行情数据的Python库。安装方法可以到官网上下载后按照默认设置进行…

    python 2023年5月14日
    00
  • Python爬取成语接龙类网站

    Python爬取成语接龙类网站是一个非常有趣的应用场景,可以帮助我们在Python中快速实现成语接龙游戏的功能。本攻略将介绍Python爬取成语接龙类网站的完整攻略,包括数据获取、数据处理、数据存储和示例。 步骤1:获取数据 在Python中,我们可以使用requests库获取网页数据。以下是获取成语接龙类网站数据的示例: import requests u…

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