iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python中怎么实现同步和异步
  • 233
分享到

Python中怎么实现同步和异步

2023-06-17 03:06:38 233人浏览 泡泡鱼

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

摘要

python中怎么实现同步和异步,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、同步与异步#同步编程(同一时间只能做一件事,做完了才能做下一件事情) 

python中怎么实现同步和异步,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

一、同步与异步

#同步编程(同一时间只能做一件事,做完了才能做下一件事情)  <-a_url-><-b_url-><-c_url->  #异步编程 (可以近似的理解成同一时间有多个事情在做,但有先后)  <-a_url->    <-b_url->      <-c_url->        <-d_url->          <-e_url->            <-f_url->              <-g_url->                <-h_url->                  <--i_url-->                    <--j_url-->

模板

import asyncio  #函数名:做现在的任务时不等待,能继续做别的任务。  async def donow_meantime_dontwait(url):      response = await requests.get(url)  #函数名:快速高效的做任务  async def fast_do_your_thing():      await asyncio.wait([donow_meantime_dontwait(url) for url in urls])  #下面两行都是套路,记住就好  loop = asyncio.get_event_loop()  loop.run_until_complete(fast_do_your_thing())

tips:

await表达式中的对象必须是awaitable

requests不支持非阻塞

aioHttp是用于异步请求的库

代码

import asyncio import requests import time import aiohttp urls = ['https://book.douban.com/tag/小说','https://book.douban.com/tag/科幻',         'https://book.douban.com/tag/漫画','https://book.douban.com/tag/奇幻',         'https://book.douban.com/tag/历史','https://book.douban.com/tag/经济学'] async def requests_meantime_dont_wait(url):     print(url)     async with aiohttp.ClientSession() as session:         async with session.get(url) as resp:             print(resp.status)             print("{url} 得到响应".fORMat(url=url)) async def fast_requsts(urls):     start = time.time()     await asyncio.wait([requests_meantime_dont_wait(url) for url in urls])     end = time.time()     print("Complete in {} seconds".format(end - start)) loop = asyncio.get_event_loop() loop.run_until_complete(fast_requsts(urls))

gevent简介

gevent是一个Python并发库,它为各种并发和网络相关的任务提供了整洁的api

gevent中用到的主要模式是greenlet,它是以C扩展模块形式接入Python的轻量级协程。 greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

猴子补丁

requests库是阻塞式的,为了将requests同步更改为异步。只有将requests库阻塞式更改为非阻塞,异步操作才能实现。

而gevent库中的猴子补丁(monkey patch),gevent能够修改标准库里面大部分的阻塞式系统调用。这样在不改变原有代码的情况下,将应用的阻塞式方法,变成协程式的(异步)。

代码

from gevent import monkey  import gevent  import requests  import time   monkey.patch_all()  def req(url):      print(url)      resp = requests.get(url)      print(resp.status_code,url)   def synchronous_times(urls):      """同步请求运行时间"""      start = time.time()      for url in urls:          req(url)      end = time.time()      print('同步执行时间 {} s'.format(end-start))   def asynchronous_times(urls):      """异步请求运行时间"""      start = time.time()      gevent.joinall([gevent.spawn(req,url) for url in urls])      end = time.time()      print('异步执行时间 {} s'.format(end - start))   urls = ['https://book.douban.com/tag/小说','https://book.douban.com/tag/科幻',          'https://book.douban.com/tag/漫画','https://book.douban.com/tag/奇幻',          'https://book.douban.com/tag/历史','https://book.douban.com/tag/经济学']   synchronous_times(urls)  asynchronous_times(urls)

gevent:异步理论与实战

Python中怎么实现同步和异步

gevent库中使用的最核心的是Greenlet-一种用C写的轻量级python模块。在任意时间,系统只能允许一个Greenlet处于运行状态

一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

串行和异步

高并发的核心是让一个大的任务分成一批子任务,并且子任务会被被系统高效率的调度,实现同步或者异步。在两个子任务之间切换,也就是经常说到的上下文切换。

同步就是让子任务串行,而异步有点影分身之术,但在任意时间点,真身只有一个,子任务并不是真正的并行,而是充分利用了碎片化的时间,让程序不要浪费在等待上。这就是异步,效率杠杆的。

gevent中的上下文切换是通过yield实现。在这个例子中,我们会有两个子任务,互相利用对方等待的时间做自己的事情。这里我们使用gevent.sleep(0)代表程序会在这里停0秒。

import gevent  def foo():      print('Running in foo')      gevent.sleep(0)      print('Explicit context switch to foo again')   def bar():      print('Explicit context to bar')      gevent.sleep(0)      print('Implicit context switch back to bar')   gevent.joinall([      gevent.spawn(foo),      gevent.spawn(bar)      ])

运行的顺序:

Running in foo  Explicit context to bar  Explicit context switch to foo again  Implicit context switch back to bar

同步异步的顺序问题

同步运行就是串行,123456...,但是异步的顺序是随机的任意的(根据子任务消耗的时间而定)

代码

import gevent  import random  def task(pid):      """      Some non-deterministic task      """      gevent.sleep(random.randint(0,2)*0.001)      print('Task %s done' % pid)    #同步(结果更像串行)  def synchronous():      for i in range(1,10):          task(i)    #异步(结果更像乱步)  def asynchronous():      threads = [gevent.spawn(task, i) for i in range(10)]      gevent.joinall(threads)    print('Synchronous同步:')  synchronous()    print('Asynchronous异步:')  asynchronous()

输出

Synchronous同步:

Task 1 done  Task 2 done  Task 3 done Task 4 done  Task 5 done  Task 6 done  Task 7 done  Task 8 done  Task 9 done

Asynchronous异步:

Task 1 done  Task 5 done  Task 6 done  Task 2 done  Task 4 done  Task 7 done  Task 8 done  Task 9 done  Task 0 done  Task 3 done

同步案例中所有的任务都是按照顺序执行,这导致主程序是阻塞式的(阻塞会暂停主程序的执行)。

gevent.spawn会对传入的任务(子任务集合)进行进行调度,gevent.joinall方法会阻塞当前程序,除非所有的greenlet都执行完毕,程序才会结束。

实战

实现gevent到底怎么用,把异步访问得到的数据提取出来。

在有道词典搜索框输入“hello”按回车。观察数据请求情况 观察有道的url构建。

分析url规律

#url构建只需要传入Word即可  url = "http://dict.youdao.com/w/eng/{}/".format(word)

解析网页数据

def fetch_word_info(word):      url = "http://dict.youdao.com/w/eng/{}/".format(word)       resp = requests.get(url,headers=headers)      doc = pq(resp.text)      pros = ''      for pro in doc.items('.baav .pronounce'):          pros+=pro.text()       description = ''      for li in doc.items('#phrsListTab .trans-container ul li'):          description +=li.text()       return {'word':word,'音标':pros,'注释':description}

因为requests库在任何时候只允许有一个访问结束完全结束后,才能进行下一次访问。无法通过正规途径拓展成异步,因此这里使用了monkey补丁

同步代码

import requests  from pyquery import PyQuery as pq  import gevent  import time  import gevent.monkey  gevent.monkey.patch_all()  words = ['Good','bad','cool',           'hot','nice','better',           'head','up','down',           'right','left','east']   def synchronous():      start = time.time()      print('同步开始了')      for word in words:          print(fetch_word_info(word))      end = time.time()      print("同步运行时间: %s 秒" % str(end - start))   #执行同步  synchronous()

异步代码

import requests  from pyquery import PyQuery as pq  import gevent  import time  import gevent.monkey  gevent.monkey.patch_all()   words = ['good','bad','cool',           'hot','nice','better',           'head','up','down',           'right','left','east']   def asynchronous():      start = time.time()      print('异步开始了')      events = [gevent.spawn(fetch_word_info,word) for word in words]      wordinfos = gevent.joinall(events)      for wordinfo in wordinfos:          #获取到数据get方法          print(wordinfo.get())      end = time.time()      print("异步运行时间: %s 秒"%str(end-start))   #执行异步  asynchronous()

我们可以对待爬网站实时异步访问,速度会大大提高。我们现在是爬取12个词语的信息,也就是说一瞬间我们对网站访问了12次,这还没啥问题,假如爬10000+个词语,使用gevent的话,那几秒钟之内就给网站一股脑的发请求,说不定网站就把爬虫封了。

解决办法

将列表等分为若干个子列表,分批爬取。举例我们有一个数字列表(0-19),要均匀的等分为4份,也就是子列表有5个数。下面是我在stackoverflow查找到的列表等分方案:

方法1

seqence = list(range(20))  size = 5 #子列表长度  output = [seqence[i:i+size] for i in range(0, len(seqence), size)]  print(output)

方法2

chunks = lambda seq, size: [seq[i: i+size] for i in range(0, len(seq), size)]  print(chunks(seq, 5))

方法3

def chunks(seq,size):      for i in range(0,len(seq), size):          yield seq[i:i+size]  prinT(chunks(seq,5))      for  x  in chunks(req,5):           print(x)

数据量不大的情况下,选哪一种方法都可以。如果特别大,建议使用方法3.

动手实现

import requests  from pyquery import PyQuery as pq  import gevent  import time  import gevent.monkey  gevent.monkey.patch_all() words = ['good','bad','cool',           'hot','nice','better',           'head','up','down',           'right','left','east']   def fetch_word_info(word):       url = "http://dict.youdao.com/w/eng/{}/".format(word)       resp = requests.get(url,headers=headers)      doc = pq(resp.text)       pros = ''      for pro in doc.items('.baav .pronounce'):          pros+=pro.text()       description = ''      for li in doc.items('#phrsListTab .trans-container ul li'):          description +=li.text()       return {'word':word,'音标':pros,'注释':description}    def asynchronous(words):      start = time.time()      print('异步开始了')        chunks = lambda seq, size: [seq[i: i + size] for i in range(0, len(seq), size)]       for subwords in chunks(words,3):          events = [gevent.spawn(fetch_word_info, word) for word in subwords]           wordinfos = gevent.joinall(events)          for wordinfo in wordinfos:              # 获取到数据get方法              print(wordinfo.get())          time.sleep(1)           end = time.time()      print("异步运行时间: %s 秒" % str(end - start))   asynchronous(words)

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网Python频道,感谢您对编程网的支持。

--结束END--

本文标题: Python中怎么实现同步和异步

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python中怎么实现同步和异步
    Python中怎么实现同步和异步,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、同步与异步#同步编程(同一时间只能做一件事,做完了才能做下一件事情) ...
    99+
    2023-06-17
  • 怎么在JavaScript中实现同步和异步
    本篇文章为大家展示了怎么在JavaScript中实现同步和异步,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。JavaScript可以做什么1.可以使网页具有交互性,例如响应用户点击,给用户提供更好的...
    99+
    2023-06-14
  • ajax中怎么实现同步异步
    ajax中怎么实现同步异步,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。$("#btn_saveFWSB"...
    99+
    2024-04-02
  • C#中怎么实现同步调用和异步调用
    今天就跟大家聊聊有关C#中怎么实现同步调用和异步调用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。C#委托的Invoke方法用来进行同步调用。同步调用也可以叫阻塞调用,它将阻塞当前线...
    99+
    2023-06-17
  • Vue中的同步调用和异步调用怎么实现
    这篇“Vue中的同步调用和异步调用怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue中的同步调用和异步调用怎么实现...
    99+
    2023-06-28
  • MySQL异步复制和半同步复制怎么实现
    这篇文章主要介绍“MySQL异步复制和半同步复制怎么实现”,在日常操作中,相信很多人在MySQL异步复制和半同步复制怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”My...
    99+
    2024-04-02
  • vue3.0中setup中异步转同步的实现
    目录vue3 setup中异步转同步vue3中setup前加上async后页面不显示子组件父组件中需要单独设置使用vue3中的异步vue3 setup中异步转同步 vue3中setu...
    99+
    2024-04-02
  • vue中同步和异步请求怎么设置
    本篇内容介绍了“vue中同步和异步请求怎么设置”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、什么是同步请求在前端开发中,我们通常使用异步...
    99+
    2023-07-06
  • Python混合怎么使用同步和异步函数
    在协程函数中调用同步函数在协程函数中直接调用同步函数会阻塞事件循环,从而影响整个程序的性能。我们先来看一个例子:以下是使用异步 Web 框架 FastAPI 写的一个例子,FastAPI 是比较快,但不正确的操作将会变得很慢。import ...
    99+
    2023-05-14
    Python
  • js异步之async和await实现同步写法
    首先我们假设有一方法 readFile 可以读取文件内容,  但是它是异步的。 var gen = function* (){     var a = yield read...
    99+
    2024-04-02
  • Python同步与异步有什么不同
    本文小编为大家详细介绍“Python同步与异步有什么不同”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python同步与异步有什么不同”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。“同步”和“异步”是什么意思?...
    99+
    2023-06-27
  • 如何在Couchbase中实现数据同步和异步复制
    在Couchbase中,数据同步和异步复制可以通过以下方法实现: 使用XDCR(跨数据中心复制):Couchbase提供了XDC...
    99+
    2024-04-02
  • Python笔记-IO同步和异步、 读写
    IO:Input/Output 由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。举个例子来说,比如要把100M的数据写入磁盘,CPU输出100M的数据只需要0.01秒,可是磁盘要接收这10...
    99+
    2023-01-31
    笔记 Python IO
  • Python中怎么实现线程同步
    这篇文章主要介绍“Python中怎么实现线程同步”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python中怎么实现线程同步”文章能帮助大家解决问题。使用 Thread 对象的 Lock 和 Rlo...
    99+
    2023-06-27
  • java中异步和同步有什么区别
    java中异步和同步有什么区别?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java的优点是什么1. 简单,只需理解基本的概念,就可以编写适合于各种情况的应用程序;2. 面向对...
    99+
    2023-06-14
  • javascript中异步和同步有什么区别
    这篇文章给大家介绍javascript中异步和同步有什么区别,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。区别:在同步中,发出一个功能调用时,必须一件一件事做,等前一件做完了才能做下一件事;而在异步中,当一个异步过程调...
    99+
    2023-06-15
  • Golang函数的同步和异步的实现方法
    Golang是一种支持并发编程的高级编程语言,它提供了丰富的并发编程机制和语法特性,方便开发者实现复杂的多线程或多协程程序。其中,同步和异步是并发编程中常用的两种方式,本文将介绍Golang函数的同步和异步的实现方法及其使用场景。一、同步函...
    99+
    2023-05-18
    异步 同步 Golang函数
  • 如何理解ajax中的async属性值同步和异步及同步和异步区别
    这篇文章给大家介绍如何理解ajax中的async属性值同步和异步及同步和异步区别,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。jquery中ajax方法有个属性async用于控制同步和...
    99+
    2024-04-02
  • python中怎么实现threading线程同步
    小编给大家分享一下python中怎么实现threading线程同步,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!说明threading模块具有实现锁定的内置功能,允许同步线程。为了防止数据损坏或丢失,需要锁定来控制共享资源...
    99+
    2023-06-20
  • 如何实现JavaScript文件的同步和异步加载
    这篇文章主要介绍了如何实现JavaScript文件的同步和异步加载,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。同步加载可在html文件里以...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作