激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - 詳解python異步編程之a(chǎn)syncio(百萬(wàn)并發(fā))

詳解python異步編程之a(chǎn)syncio(百萬(wàn)并發(fā))

2021-03-14 00:13三只松鼠 Python

這篇文章主要介紹了詳解python異步編程之a(chǎn)syncio(百萬(wàn)并發(fā)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

前言:python由于GIL(全局鎖)的存在,不能發(fā)揮多核的優(yōu)勢(shì),其性能一直飽受詬病。然而在IO密集型的網(wǎng)絡(luò)編程里,異步處理比同步處理能提升成百上千倍的效率,彌補(bǔ)了python性能方面的短板,如最新的微服務(wù)框架japronto,resquests per second可達(dá)百萬(wàn)級(jí)。

python還有一個(gè)優(yōu)勢(shì)是庫(kù)(第三方庫(kù))極為豐富,運(yùn)用十分方便。asyncio是python3.4版本引入到標(biāo)準(zhǔn)庫(kù),python2x沒(méi)有加這個(gè)庫(kù),畢竟python3x才是未來(lái)啊,哈哈!python3.5又加入了async/await特性。

在學(xué)習(xí)asyncio之前,我們先來(lái)理清楚同步/異步的概念:

同步是指完成事務(wù)的邏輯,先執(zhí)行第一個(gè)事務(wù),如果阻塞了,會(huì)一直等待,直到這個(gè)事務(wù)完成,再執(zhí)行第二個(gè)事務(wù),順序執(zhí)行。。。

異步是和同步相對(duì)的,異步是指在處理調(diào)用這個(gè)事務(wù)的之后,不會(huì)等待這個(gè)事務(wù)的處理結(jié)果,直接處理第二個(gè)事務(wù)去了,通過(guò)狀態(tài)、通知、回調(diào)來(lái)通知調(diào)用者處理結(jié)果。

一、asyncio

下面通過(guò)舉例來(lái)對(duì)比同步代碼和異步代碼編寫(xiě)方面的差異,其次看下兩者性能上的差距,我們使用sleep(1)模擬耗時(shí)1秒的io操作。

同步代碼:

?
1
2
3
4
5
6
7
8
9
10
11
import time
 
def hello():
  time.sleep(1)
 
def run():
  for i in range(5):
    hello()
    print('Hello World:%s' % time.time()) # 任何偉大的代碼都是從Hello World 開(kāi)始的!
if __name__ == '__main__':
  run()

輸出:(間隔差不多是1s)

Hello World:1527595175.4728756
Hello World:1527595176.473001
Hello World:1527595177.473494
Hello World:1527595178.4739306
Hello World:1527595179.474482 

異步代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import time
import asyncio
 
# 定義異步函數(shù)
async def hello():
  asyncio.sleep(1)
  print('Hello World:%s' % time.time())
 
def run():
  for i in range(5):
    loop.run_until_complete(hello())
 
loop = asyncio.get_event_loop()
if __name__ =='__main__':
  run()

輸出:

Hello World:1527595104.8338501
Hello World:1527595104.8338501
Hello World:1527595104.8338501
Hello World:1527595104.8338501
Hello World:1527595104.8338501 

async def 用來(lái)定義異步函數(shù),其內(nèi)部有異步操作。每個(gè)線程有一個(gè)事件循環(huán),主線程調(diào)用asyncio.get_event_loop()時(shí)會(huì)創(chuàng)建事件循環(huán),你需要把異步的任務(wù)丟給這個(gè)循環(huán)的run_until_complete()方法,事件循環(huán)會(huì)安排協(xié)同程序的執(zhí)行。  

二、aiohttp

如果需要并發(fā)http請(qǐng)求怎么辦呢,通常是用requests,但requests是同步的庫(kù),如果想異步的話需要引入aiohttp。這里引入一個(gè)類,from aiohttp import ClientSession,首先要建立一個(gè)session對(duì)象,然后用session對(duì)象去打開(kāi)網(wǎng)頁(yè)。session可以進(jìn)行多項(xiàng)操作,比如post, get, put, head等。

基本用法:

?
1
2
async with ClientSession() as session:
async with session.get(url) as response:

aiohttp異步實(shí)現(xiàn)的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import asyncio
from aiohttp import ClientSession
 
 
tasks = []
url = "https://www.baidu.com/{}"
async def hello(url):
  async with ClientSession() as session:
    async with session.get(url) as response:
      response = await response.read()
      print(response)
 
if __name__ == '__main__':
  loop = asyncio.get_event_loop()
  loop.run_until_complete(hello(url))

首先async def 關(guān)鍵字定義了這是個(gè)異步函數(shù),await 關(guān)鍵字加在需要等待的操作前面,response.read()等待request響應(yīng),是個(gè)耗IO操作。然后使用ClientSession類發(fā)起http請(qǐng)求。

多鏈接異步訪問(wèn)

如果我們需要請(qǐng)求多個(gè)URL該怎么辦呢,同步的做法訪問(wèn)多個(gè)URL只需要加個(gè)for循環(huán)就可以了。但異步的實(shí)現(xiàn)方式并沒(méi)那么容易,在之前的基礎(chǔ)上需要將hello()包裝在asyncio的Future對(duì)象中,然后將Future對(duì)象列表作為任務(wù)傳遞給事件循環(huán)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time
import asyncio
from aiohttp import ClientSession
 
tasks = []
url = "https://www.baidu.com/{}"
async def hello(url):
  async with ClientSession() as session:
    async with session.get(url) as response:
      response = await response.read()
#      print(response)
      print('Hello World:%s' % time.time())
 
def run():
  for i in range(5):
    task = asyncio.ensure_future(hello(url.format(i)))
    tasks.append(task)
 
 
if __name__ == '__main__':
  loop = asyncio.get_event_loop()
  run()
  loop.run_until_complete(asyncio.wait(tasks))

輸出:

Hello World:1527754874.8915546
Hello World:1527754874.899039
Hello World:1527754874.90004
Hello World:1527754874.9095392
Hello World:1527754874.9190395 

收集http響應(yīng)

好了,上面介紹了訪問(wèn)不同鏈接的異步實(shí)現(xiàn)方式,但是我們只是發(fā)出了請(qǐng)求,如果要把響應(yīng)一一收集到一個(gè)列表中,最后保存到本地或者打印出來(lái)要怎么實(shí)現(xiàn)呢,可通過(guò)asyncio.gather(*tasks)將響應(yīng)全部收集起來(lái),具體通過(guò)下面實(shí)例來(lái)演示。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time
import asyncio
from aiohttp import ClientSession
 
tasks = []
url = "https://www.baidu.com/{}"
async def hello(url):
  async with ClientSession() as session:
    async with session.get(url) as response:
#      print(response)
      print('Hello World:%s' % time.time())
      return await response.read()
 
def run():
  for i in range(5):
    task = asyncio.ensure_future(hello(url.format(i)))
    tasks.append(task)
  result = loop.run_until_complete(asyncio.gather(*tasks))
  print(result)
 
if __name__ == '__main__':
  loop = asyncio.get_event_loop()
  run()

輸出:

Hello World:1527765369.0785167
Hello World:1527765369.0845182
Hello World:1527765369.0910277
Hello World:1527765369.0920424
Hello World:1527765369.097017
[b'<!DOCTYPE html>\r\n<!--STATUS OK-->\r\n<html>\r\n<head>\r\n......

異常解決

假如你的并發(fā)達(dá)到1000個(gè),程序會(huì)報(bào)錯(cuò):ValueError: too many file descriptors in select()。這個(gè)報(bào)錯(cuò)的原因是因?yàn)?Python 調(diào)取的 select 對(duì)打開(kāi)的文件字符有最大長(zhǎng)度限制。這里我們有兩種方法解決這個(gè)問(wèn)題:1.我們可以需要限制并發(fā)數(shù)量。一次不要塞那么多任務(wù),或者限制最大并發(fā)數(shù)量。2.我們可以使用回調(diào)的方式。這里個(gè)人推薦限制并發(fā)數(shù)的方法,設(shè)置并發(fā)數(shù)為500或者600,處理速度更快。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#coding:utf-8
import time,asyncio,aiohttp
 
 
url = 'https://www.baidu.com/'
async def hello(url,semaphore):
  async with semaphore:
    async with aiohttp.ClientSession() as session:
      async with session.get(url) as response:
        return await response.read()
 
 
async def run():
  semaphore = asyncio.Semaphore(500) # 限制并發(fā)量為500
  to_get = [hello(url.format(),semaphore) for _ in range(1000)] #總共1000任務(wù)
  await asyncio.wait(to_get)
 
 
if __name__ == '__main__':
#  now=lambda :time.time()
  loop = asyncio.get_event_loop()
  loop.run_until_complete(run())
  loop.close()

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.cnblogs.com/shenh/p/9090586.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 一级片国语 | 九九热视频免费在线观看 | 国产成人精品一区二区仙踪林 | 国产精品视频一区二区三区四 | 中文在线免费观看 | 中文字幕在线免费观看电影 | 黄视频免费在线观看 | 中文字幕一二三区芒果 | 欧美人与物videos另类 | 黄色99视频 | 成人黄色小视频网站 | 蜜桃传免费看片www 日本一区二区三区视频在线 | 日本一区二区久久久 | 黄色7777| 国产乱xxxx| 精品一区二区三区中文字幕老牛 | 国产精品伊人久久 | 亚洲午夜网站 | 少妇一级淫片免费放4p | 精品国产91久久久久久久 | 国内xxxx乱子另类 | 自拍偷拍亚洲图片 | 九色激情网 | 国产流白浆高潮在线观看 | 国产成人羞羞视频在线 | 97久久曰曰久久久 | 日韩av日韩| 成人福利电影在线观看 | 久久成人免费网站 | 做爰xxxⅹ性护士hd在线 | 欧美一级黄色片在线观看 | 免费观看黄色片视频 | 黄视频网址 | 日韩.www| 久久精品中文字幕一区二区三区 | 日本黄色不卡视频 | 永久免费不卡在线观看黄网站 | 精品久久久一二三区播放播放播放视频 | 久久精品国产99国产精品亚洲 | 91 免费看片 | 色婷婷av一区二区三区久久 |