返回顶部
首页 > 资讯 > 后端开发 > Python >Python中的并发处理之使用asyn
  • 312
分享到

Python中的并发处理之使用asyn

Pythonasyn 2023-01-31 08:01:02 312人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

导语:本文章记录了本人在学习Python基础之控制流程篇的重点知识及个人心得,打算入门python的朋友们可以来一起学习并交流。 本文重点: 1、了解asyncio包的功能和使用方法;2、了解如何避免阻塞型调用;3、学会使用协程避免回调地

导语:本文章记录了本人在学习Python基础之控制流程篇的重点知识及个人心得,打算入门python的朋友们可以来一起学习并交流。

本文重点:

1、了解asyncio包的功能和使用方法;
2、了解如何避免阻塞型调用;
3、学会使用协程避免回调地狱。

一、使用asyncio包做并发编程

1、并发与并行

并发:一次处理多件事。
并行:一次做多件事。
并发用于制定方案,用来解决可能(但未必)并行的问题。并发更好。

2、asyncio概述

了解asyncio的4个特点:

  • asyncio包使用事件循环驱动的协程实现并发。
  • 适合asyncio api的协程在定义体中必须使用yield from,而不能使用yield。
  • 使用asyncio处理的协程,需在定义体上使用@asyncio.coroutine装饰。装饰的功能在于凸显协程,同时当协程不产出值,协程会被垃圾回收。
  • python3.4起,asyncio包只直接支持tcp和UDP协议。如果想使用asyncio实现Http客户端和服务器时,常使用aiohttp包。

在协程中使用yield from需要注意两点:

  • 使用yield froml链接的多个协程最终必须由不是协程的调用方驱动,调用方显式或隐式在最外层委派生成器上调用next()函数或 .send()方法。
  • 链条中最内层的子生成器必须是简单的生成器(只使用yield)或可迭代的对象。

但在asyncio包的API中使用yield from还需注意两个细节:

  • asyncio包中编写的协程链条始终通过把最外层委派生成器传给asyncio包API中的某个函数驱动,例如loop.run_until_complete()。即不通过调用next()函数或 .send()方法驱动协程。
  • 编写的协程链条最终通过yield from把职责委托给asyncio包中的某个协程函数或协程方法。即最内层的子生成器是库中真正执行I/O操作的函数,而不是我们自己编写的函数。

实例——通过asyncio包和协程以动画形式显示文本式旋转指针:

import asyncio
import itertools
import sys

@asyncio.coroutine  # 交给 asyncio 处理的协程要使用 @asyncio.coroutine 装饰
def spin(msg):
    for char in itertools.cycle('|/-\\'):
        status = char + ' ' + msg
        print(status)
        try:
            yield from asyncio.sleep(.1)  # 使用 yield from asyncio.sleep(.1) 代替 time.sleep(.1),这样的休眠不会阻塞事件循环。
        except asyncio.CancelledError:  # 如果 spin 函数苏醒后抛出 asyncio.CancelledError 异常,其原因是发出了取消请求,因此退出循环。
            break

@asyncio.coroutine
def slow_function():  # slow_function 函数是协程,在用休眠假装进行 I/O 操作时,使用 yield from 继续执行事件循环。
    # 假装等待I/O一段时间
    yield from asyncio.sleep(3)  # yield from asyncio.sleep(3) 表达式把控制权交给主循环,在休眠结束后恢复这个协程。
    return 42

@asyncio.coroutine
def supervisor():  # supervisor 函数也是协程
    spinner = asyncio.async(spin('thinking!'))  # asyncio.async(...) 函数排定 spin 协程的运行时间,使用一个 Task 对象包装spin 协程,并立即返回。
    print('spinner object:', spinner)
    result = yield from slow_function()  # 驱动 slow_function() 函数。结束后,获取返回值。
# 同时,事件循环继续运行,因为slow_function 函数最后使用 yield from asyncio.sleep(3) 表达式把控制权交回给了主循环。
    spinner.cancel()  # Task 对象可以取消;取消后会在协程当前暂停的 yield 处抛出 asyncio.CancelledError 异常。协程可以捕获这个异常,也可以延迟取消,甚至拒绝取消。
    return result

if __name__ == '__main__':
    loop = asyncio.get_event_loop()  # 获取事件循环的引用
    result = loop.run_until_complete(supervisor())  # 驱动 supervisor 协程,让它运行完毕;这个协程的返回值是这次调用的返回值。
    loop.close()
    print('Answer:', result)

3、线程与协程对比

线程调度程序在任何时候都能中断线程。必须记住保留。去保护程序中的重要部分,防止多步操作在执行的过程中中断,防止数据处于无效状态。
协程默认会做好全方位保护,以防止中断。对协程来说无需保留锁,在多个线程之间同步操作,协程自身就会同步,因为在任意时刻只有一个协程运行。

4、从期物、任务和协程中产出

在asyncio包中,期物和协程关系紧密,因为可以使用yield from从asyncio.Future对象中产出结果。这意味着,如果foo是协程函数,抑或是返回Future或Task实例的普通函数,那么可以这样写:res=yield from foo()。这是asyncio包中很多地方可以互换协程与期物的原因之一。

二、避免阻塞型调用

1、有两种方法能避免阻塞型调用中止整个应用程序的进程:

  • 在单独的线程中运行各个阻塞型操作。
  • 把每个阻塞型操作转换成非阻塞的异步调用。

使用多线程处理大量连接时将耗费过多的内存,故此通常使用回调来实现异步调用。

2、使用Executor对象防止阻塞事件循环:

  • 使用loop.run_in_executor把阻塞的作业(例如保存文件)委托给线程池做。
@asyncio.coroutine
def download_one(cc, base_url, semaphore, verbose):
    try:
        with (yield from semaphore):
            image = yield from get_flag(base_url, cc)
    except WEB.HTTPNotFound:
        status = httpstatus.not_found
        msg = 'not found'
    except Exception as exc:
        raise FetchError(cc) from exc
    else:
        loop = asyncio.get_event_loop()  # 获取事件循环对象的引用
        loop.run_in_executor(None,  # None 使用默认的 TrreadPoolExecutor 实例
                save_flag, image, cc.lower() + '.gif')  # 传入可调用对象
        status = HTTPStatus.ok
        msg = 'OK'

    if verbose and msg:
        print(cc, msg)

    return Result(status, cc)

asyncio 的事件循环背后维护一个 ThreadPoolExecutor 对象,我们可以调用 run_in_executor 方法, 把可调用的对象发给它执行。

三、从回调到期物和协程

回调地狱:如果一个操作需要依赖之前操作的结果,那就得嵌套回调。
Python 中的回调地狱:

def stage1(response1):
    request2 = step1(response1)
    api_call2(request2, stage2)

def stage2(response2):
    request3 = step2(response2)
    api_call3(request3, stage3)

def stage3(response3):
    step3(response3)

api_call1(request1, step1)

使用 协程 和 yield from 结构做异步编程,无需用回调:

@asyncio.coroutine
def three_stages(request1):
    response1 = yield from api_call1()
    request2 = step1(response1)
    response2 = yield from api_call2(request2)
    request3 = step2(response2)
    response3 = yield from api_call3(request3)
    step3(response3)

loop.create_task(three_stages(request1))
# 协程不能直接调用,必须用事件循环显示指定协程的执行时间,或者在其他排定了执行时间的协程中使用 yield from 表达式把它激活

四、使用asyncio包编写服务器

  • 使用asyncio包能实现TCP和HTTP服务器
  • Web服务将成为asyncio包的重要使用场景。

--结束END--

本文标题: Python中的并发处理之使用asyn

本文链接: https://lsjlt.com/news/192505.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python中的并发处理之使用asyn
    导语:本文章记录了本人在学习Python基础之控制流程篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。 本文重点: 1、了解asyncio包的功能和使用方法;2、了解如何避免阻塞型调用;3、学会使用协程避免回调地...
    99+
    2023-01-31
    Python asyn
  • python使用期物处理并发的方法
    这篇文章主要介绍“python使用期物处理并发的方法”,在日常操作中,相信很多人在python使用期物处理并发的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”python使用期物处理并发的方法”的疑惑有所...
    99+
    2023-07-02
  • Python并发处理
    1.创建并销毁线程#!/usr/bin/python #code to execute in an independent thread import time def countdown(n):     while n > 0:...
    99+
    2023-01-31
    Python
  • python使用期物处理并发教程
    目录1. futures.ThreadPoolExecutor2. 期物3. 阻塞型I/O和GIL4. 使用concurrent.futures模块启动进程learning from...
    99+
    2024-04-02
  • Python使用asyncio包处理并发的实现代码
    使用 asyncio 包处理并发 asyncio包:使用事件循环驱动的协程实现并发。 线程与协程的对比 '\ thinking' 旋转等待效果 In [1]: imp...
    99+
    2022-12-08
    Python asyncio包 Python asyncio包处理并发
  • 解密Java中HTTP并发处理和JavaScript的异同之处
    Java和JavaScript是两种不同的编程语言,但它们在Web开发中都起着重要的作用。其中,Java在Web服务器端广泛应用于HTTP并发处理,而JavaScript则主要用于前端开发。本文将,通过演示代码帮助读者更好地理解它们的区别和...
    99+
    2023-09-06
    http 并发 javascript
  • Python使用future处理并发问题方案详解
    目录网络下载的三种风格按照顺序下载使用conrurrent.futures模块多线程下载使用asyncio异步下载future是什么GIL和阻塞型I/O使用concurrent.fu...
    99+
    2023-02-08
    Python future处理并发 Python future Python future并发问题
  • Java并发之BlockingQueue的使用
    Java的并发包中提供了一个BlockingQueue接口,它是一个支持线程安全的队列,并且在队列为空时会阻塞消费者线程,直到队列不...
    99+
    2023-08-11
    java
  • 如何使用 Python 函数实现高效的并发处理?
    Python 是一种高级语言,使用它编写的程序可以在许多领域得到应用。Python 函数的强大之处在于,它可以让我们以一种高效的方式实现并发处理。在本文中,我们将介绍如何使用 Python 函数实现高效的并发处理。 并发处理是一种实现多任务...
    99+
    2023-08-29
    函数 实时 并发
  • PHP开发中如何处理接口并发请求和并发处理
    在实际的Web开发中,我们经常会遇到并发请求的情况。并发请求是指多个请求同时发送给服务器进行处理。如果我们的应用程序无法正确处理并发请求,就有可能导致数据不一致、性能下降等问题。本文将介绍如何在PHP开发中处理接口的并发请求和并发处理,并提...
    99+
    2023-10-21
    接口 并发处理 并发请求
  • php怎么使用redis处理高并发
    使用Redis处理高并发可以通过以下几个步骤实现: 安装Redis:首先要在服务器上安装Redis,可以参考Redis官方文档的...
    99+
    2023-10-23
    php redis
  • java并发编程之深入理解Synchronized的使用
    1.为什么要使用synchronized 在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。关键字synchronized可以保证在同一时刻,只...
    99+
    2024-04-02
  • 如何用Python处理LeetCode数组题目中的并发问题?
    LeetCode是一家知名的在线编程练习平台,提供了许多经典的算法和数据结构题目,让程序员们可以在实战中提高自己的编程能力。其中,数组题目是比较常见的一类,但是在处理一些并发问题时,可能会遇到一些棘手的难题。那么,如何用Python来解决...
    99+
    2023-11-05
    数组 leetcode 并发
  • Java并发编程之CountDownLatch的使用
    目录前言基本使用await尝试获取锁获取锁失败countDown方法前言 CountDownLatch是一个倒数的同步器,和其他同步器不同的是,state为0时表示获取锁成功。常用来...
    99+
    2023-05-20
    Java并发编程CountDownLatch Java CountDownLatch使用 Java CountDownLatch
  • Java并发实例之CyclicBarrier的使用
    最近一直整并发这块东西,顺便写点Java并发的例子,给大家做个分享,也强化下自己记忆,如果有什么错误或者不当的地方,欢迎大家斧正。CyclicBarrier是一种多线程并发控制实用工具,和CountDownLatch非常类似,它也可以实现线...
    99+
    2023-05-30
    java 并发 cyclicbarrier
  • Python编程技巧:使用并发处理HTTP请求并生成二维码。
    Python编程技巧:使用并发处理HTTP请求并生成二维码 在当今互联网时代,我们经常需要从网络上获取数据,比如爬取网站数据、下载图片、视频等等。当需要处理大量的HTTP请求时,使用并发处理是提高程序效率的一种常用方法。本文将介绍如何使用P...
    99+
    2023-09-21
    http 二维码 并发
  • 如何在PHP中使用Shell实现对象的并发处理?
    PHP是一种流行的编程语言,用于开发Web应用程序。尽管PHP本身是单线程的,但是通过使用Shell,我们可以实现PHP中的对象并发处理,提高应用程序的性能和可扩展性。 本文将介绍如何在PHP中使用Shell实现对象的并发处理。 一、She...
    99+
    2023-10-22
    对象 并发 shell
  • java高并发处理 java处理高并发的几种方法
    一、背景综述         并发就是可以使用多个线程或进程,同时处理(就是并发)不同的操作。         高并发的时候就是有很多用户在访问,导致系统数据不正确、糗事数据的现象。对于一些大型网站,比如门户网站,在面对大量用户访问、高并发...
    99+
    2023-09-22
    java
  • 如何使用Go WaitGroup处理并发任务
    在 Go 中使用 `sync.WaitGroup` 来处理并发任务,可以确保在所有任务完成之前等待主程序的执行。下面是一个简单的例子...
    99+
    2023-10-09
    Golang
  • 怎么使用go并发处理同样的数据
    在Go语言中,可以使用goroutine和channel来实现并发处理同样的数据。下面是一个简单的示例: package main ...
    99+
    2024-02-29
    go
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作