最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中asyncio與aiohttp入門教程

 更新時間:2018年10月16日 09:42:59   作者:數(shù)據(jù)架構(gòu)師  
今天小編就為大家分享一篇關(guān)于Python中asyncio與aiohttp入門教程,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧

很多朋友對異步編程都處于“聽說很強大”的認知狀態(tài)。鮮有在生產(chǎn)項目中使用它。而使用它的同學,則大多數(shù)都停留在知道如何使用 Tornado、Twisted、Gevent 這類異步框架上,出現(xiàn)各種古怪的問題難以解決。而且使用了異步框架的部分同學,由于用法不對,感覺它并沒牛到哪里去,所以很多同學做 Web 后端服務(wù)時還是采用 Flask、Django等傳統(tǒng)的非異步框架。

從上兩屆 PyCon 技術(shù)大會看來,異步編程已經(jīng)成了 Python 生態(tài)下一階段的主旋律。如新興的 Go、Rust、Elixir 等編程語言都將其支持異步和高并發(fā)作為主要“賣點”,技術(shù)變化趨勢如此。Python 生態(tài)為不落人后,從2013年起由 Python 之父 Guido 親自操刀主持了Tulip(asyncio)項目的開發(fā)。

異步io的好處在于避免的線程的開銷和切換,而且我們都知道python其實是沒有多線程的,只是通過底層線層鎖實現(xiàn)的多線程。另一個好處在于避免io操作(包含網(wǎng)絡(luò)傳輸)的堵塞時間。

asyncio可以實現(xiàn)單線程并發(fā)IO操作。如果僅用在客戶端,發(fā)揮的威力不大。如果把asyncio用在服務(wù)器端,例如Web服務(wù)器,由于HTTP連接就是IO操作,因此可以用單線程+coroutine實現(xiàn)多用戶的高并發(fā)支持。

asyncio實現(xiàn)了TCP、UDP、SSL等協(xié)議,aiohttp則是基于asyncio實現(xiàn)的HTTP框架。

  • 對于異步io你需要知道的重點,要注意的是,await語法只能出現(xiàn)在通過async修飾的函數(shù)中,否則會報SyntaxError錯誤。而且await后面的對象需要是一個Awaitable,或者實現(xiàn)了相關(guān)的協(xié)議。

注意:

  • 所有需要異步執(zhí)行的函數(shù),都需要asyncio中的輪訓器去輪訓執(zhí)行,如果函數(shù)阻塞,輪訓器就會去執(zhí)行下一個函數(shù)。所以所有需要異步執(zhí)行的函數(shù)都需要加入到這個輪訓器中。

asyncio

asyncio的基本概念asyncio是在python3.4中被引進的異步IO庫。你也可以通過python3.3的pypi來安裝它。它相當?shù)膹?fù)雜,而且我不會介紹太多的細節(jié)。相反,我將會解釋你需要知道些什么,以利用它來寫異步的代碼。簡而言之,有兩件事情你需要知道:協(xié)同程序和事件循環(huán)。協(xié)同程序像是方法,但是它們可以在代碼中的特定點暫停和繼續(xù)。當在等待一個IO(比如一個HTTP請求),同時執(zhí)行另一個請求的時候,可以用來暫停一個協(xié)同程序。

例如:

import requests
import time
import asyncio
# 創(chuàng)建一個異步函數(shù)
async def task_func():
  await asyncio.sleep(1)
  resp = requests.get('http://192.168.2.177:5002/')
  print('2222222',time.time(),resp.text)
async def main(loop):
  loop=asyncio.get_event_loop()  # 獲取全局輪訓器
  task = loop.create_task(task_func()) # 在全局輪訓器加入?yún)f(xié)成,只有加入全局輪訓器才能被監(jiān)督執(zhí)行
  await asyncio.sleep(2)  # 等待兩秒為了不要立即執(zhí)行event_loop.close(),項目中event_loop應(yīng)該是永不停歇的
  print('11111111111',time.time())
event_loop = asyncio.get_event_loop()
try:
  event_loop.run_until_complete(main(event_loop))
finally:
  event_loop.close()  # 當輪訓器關(guān)閉以后,所有沒有執(zhí)行完成的協(xié)成將全部關(guān)閉

aiohttp服務(wù)器

下面是aiohttp作為服務(wù)器端的一個簡單的demo。

#!/usr/bin/env python3
import argparse
from aiohttp import web
import asyncio
import base64
import logging
import uvloop
import time,datetime
import json
import requests
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
routes = web.RouteTableDef()
@routes.get('/')
async def hello(request):
  return web.Response(text="Hello, world")
# 定義一個路由映射,接收網(wǎng)址參數(shù),post方式
@routes.post('/demo1/{name}')
async def demo1(request):  # 異步監(jiān)聽,只要一有握手就開始觸發(fā),此時網(wǎng)址參數(shù)中的name就已經(jīng)知道了,但是前端可能還沒有完全post完數(shù)據(jù)。
  name = request.match_info.get('name', "Anonymous") # 獲取name
  print(datetime.datetime.now())  # 觸發(fā)視圖函數(shù)的時間
  data = await request.post()  # 等待post數(shù)據(jù)完成接收,只有接收完成才能進行后續(xù)操作.data['key']獲取參數(shù)
  print(datetime.datetime.now())  # 接收post數(shù)據(jù)完成的時間
  logging.info('safety dect request start %s' % datetime.datetime.now())
  result = {'name':name,'key':data['key']}
  logging.info('safety dect request finish %s, %s' % (datetime.datetime.now(),json.dumps(result)))
  return web.json_response(result)
# 定義一個路由映射,設(shè)計到io操作
@routes.post('/demo2')
async def demo2(request):  # 異步監(jiān)聽,只要一有握手就開始觸發(fā),此時網(wǎng)址參數(shù)中的name就已經(jīng)知道了,但是前端可能還沒有完全post完數(shù)據(jù)。
  data = await request.post()  # 等待post數(shù)據(jù)完成接收,只有接收完成才能進行后續(xù)操作.data['key']獲取參數(shù)
  logging.info('safety dect request start %s' % datetime.datetime.now())
  res = requests.post('http://www.baidu.com')  # 網(wǎng)路id,會自動切換到其他協(xié)成上
  logging.info('safety dect request finish %s' % res.test)
  return web.Response(text="welcome")
if __name__ == '__main__':
  logging.info('server start')
  app = web.Application()
  app.add_routes(routes)
  web.run_app(app,host='0.0.0.0',port=8080)
  logging.info('server close')

aiohttp客戶端

aiohttp的另一個主要作用是作為異步客戶端,用來解決高并發(fā)請求的情況。比如現(xiàn)在我要模擬一個高并發(fā)請求來測試我的服務(wù)器負載情況。所以需要在python里模擬高并發(fā)。高并發(fā)可以有多種方式,比如多線程,但是由于python本質(zhì)上是沒有多線程的,通過底層線程鎖實現(xiàn)的多線程。在模型高并發(fā)時,具有線程切換和線程開銷的損耗。所以我們就可以使用多協(xié)成來實現(xiàn)高并發(fā)。

我們就可以使用aiohttp來模擬高并發(fā)客戶端。demo如下,用來模擬多個客戶端向指定服務(wù)器post圖片。

# 異步并發(fā)客戶端
class Asyncio_Client(object):
  def __init__(self):
    self.loop=asyncio.get_event_loop()
    self.tasks=[]
  # 將異步函數(shù)介入任務(wù)列表。后續(xù)參數(shù)直接傳給異步函數(shù)
  def set_task(self,task_fun,num,*args):
    for i in range(num):
      self.tasks.append(task_fun(*args))
  # 運行,獲取返回結(jié)果
  def run(self):
    back=[]
    try:
      f = asyncio.wait(self.tasks)  # 創(chuàng)建future
      self.loop.run_until_complete(f) # 等待future完成
    finally:
      pass
# 服務(wù)器高并發(fā)壓力測試
class Test_Load():
  total_time=0 # 總耗時
  total_payload=0 # 總負載
  total_num=0 # 總并發(fā)數(shù)
  all_time=[]
  # 創(chuàng)建一個異步任務(wù),本地測試,所以post和接收幾乎不損耗時間,可以等待完成,主要耗時為算法模塊
  async def task_func1(self,session):
    begin = time.time()
    # print('開始發(fā)送:', begin)
    file=open(self.image, 'rb')
    fsize = os.path.getsize(self.image)
    self.total_payload+=fsize/(1024*1024)
    data = {"image_id": "2", 'image':file}
    r = await session.post(self.url,data=data) #只post,不接收
    result = await r.json()
    self.total_num+=1
    # print(result)
    end = time.time()
    # print('接收完成:', end,',index=',self.total_num)
    self.all_time.append(end-begin)
  # 負載測試
  def test_safety(self):
    print('test begin')
    async_client = Asyncio_Client() # 創(chuàng)建客戶端
    session = aiohttp.ClientSession()
    for i in range(10): # 執(zhí)行10次
      self.all_time=[]
      self.total_num=0
      self.total_payload=0
      self.image = 'xxxx.jpg' # 設(shè)置測試nayizhang
      print('測試圖片:', self.image)
      begin = time.time()
      async_client.set_task(self.task_func1,self.num,session) # 設(shè)置并發(fā)任務(wù)
      async_client.run()  # 執(zhí)行任務(wù)
      end=time.time()
      self.all_time.sort(reverse=True)
      print(self.all_time)
      print('并發(fā)數(shù)量(個):',self.total_num)
      print('總耗時(s):',end-begin)
      print('最大時延(s):',self.all_time[0])
      print('最小時延(s):', self.all_time[len(self.all_time)-1])
      print('top-90%時延(s):', self.all_time[int(len(self.all_time)*0.1)])
      print('平均耗時(s/個):',sum(self.all_time)/self.total_num)
      print('支持并發(fā)率(個/s):',self.total_num/(end-begin))
      print('總負載(MB):',self.total_payload)
      print('吞吐率(MB/S):',self.total_payload/(end-begin))  # 吞吐率受上行下行帶寬,服務(wù)器帶寬,服務(wù)器算法性能諸多影響
      time.sleep(3)
    session.close()
    print('test finish')

aiohttp服務(wù)器mvc(靜態(tài)網(wǎng)頁,模板,數(shù)據(jù)庫,log)

aiohttp之添加靜態(tài)資源路徑

所謂靜態(tài)資源,是指圖片、js、css等文件。

以一個小項目來說明,下面是項目的目錄結(jié)構(gòu):

.
├── static
│  ├── css
│  │  ├── base.css
│  │  ├── bootstrap.min.css
│  │  └── font-awesome.min.css
│  ├── font
│  │  ├── FontAwesome.otf
│  │  ├── fontawesome-webfont.eot
│  │  ├── fontawesome-webfont.svg
│  │  ├── fontawesome-webfont.ttf
│  │  └── fontawesome-webfont.woff
│  └── index.html
└── proxy_server.py

在proxy_server.py給2個靜態(tài)文件目錄static/css和static/font添加路由:

app.router.add_static('/css/',
            path='static/css',
            name='css')
app.router.add_static('/font/',
            path='static/font',
            name='font')

必需的2個參數(shù):

prefix:是靜態(tài)文件的url的前綴,以/開始,在瀏覽器地址欄上顯示在網(wǎng)站host之后,也用于index.html靜態(tài)頁面進行引用
path:靜態(tài)文件目錄的路徑,可以是相對路徑,上面代碼使用的static/css就是相對路徑——相對于proxy_server.py所在路徑。

加載的是index.html,下面是它引用靜態(tài)資源的代碼:

<!-- Bootstrap CSS -->
<link href="css/bootstrap.min.css" rel="external nofollow" rel="stylesheet">
<!-- Base CSS -->
<link href="css/base.css" rel="external nofollow" rel="stylesheet">
<!-- FA CSS -->
<link href="css/font-awesome.min.css" rel="external nofollow" rel="stylesheet">

添加font的路徑是因為/font-awesome.min.css需要使用:

如果修改前綴:

 app.router.add_static('/css2017/',
            path='static/css',
            name='css')

雖然目錄本身還是css,但通過add_static已經(jīng)將它視為了css2017,在文件和瀏覽器中要想鏈接到css下的文件,必須使用css2017/xx.css來鏈接。

此外,如果加上show_index=True,就可以顯示靜態(tài)資源的目錄索引了——默認是禁止訪問的:

app.router.add_static('/css2017/',
            path='static/css',
            name='css',
            show_index=True)

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接

相關(guān)文章

  • Python實現(xiàn)簡易凱撒密碼的示例代碼

    Python實現(xiàn)簡易凱撒密碼的示例代碼

    密碼的使用最早可以追溯到古羅馬時期,《高盧戰(zhàn)記》有描述愷撒曾經(jīng)使用密碼來傳遞信息,即所謂的“愷撒密碼”。本文將利用Python實現(xiàn)簡易的凱撒密碼,感興趣的可以了解一下
    2022-09-09
  • Python中web錯誤處理與異常捕獲示例詳解

    Python中web錯誤處理與異常捕獲示例詳解

    在任何編程語言中,異常(Exception)都是一種不可避免的現(xiàn)象,它們通常是由程序運行時的錯誤或意外情況引起的,這篇文章主要介紹了Python中web錯誤處理與異常捕獲的相關(guān)資料,需要的朋友可以參考下
    2025-07-07
  • Python多層裝飾器用法實例分析

    Python多層裝飾器用法實例分析

    這篇文章主要介紹了Python多層裝飾器用法,結(jié)合實例形式簡單分析了Python多層裝飾器的相關(guān)使用方法與注意事項,需要的朋友可以參考下
    2018-02-02
  • python爬蟲爬取微博評論案例詳解

    python爬蟲爬取微博評論案例詳解

    這篇文章主要介紹了python爬蟲爬取微博評論,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • python中使用%與.format格式化文本方法解析

    python中使用%與.format格式化文本方法解析

    這篇文章主要介紹了python中使用%與.format格式化文本方法解析,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • Python進行Socket接口測試的實現(xiàn)

    Python進行Socket接口測試的實現(xiàn)

    Python 提供了強大且易于使用的 socket 模塊,使開發(fā)者能夠輕松地創(chuàng)建客戶端和服務(wù)器應(yīng)用,實現(xiàn)數(shù)據(jù)傳輸和交互,本文主要介紹了Python進行Socket接口測試的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • 基于PyQt5完成的PDF拆分功能

    基于PyQt5完成的PDF拆分功能

    這篇文章主要介紹了基于PyQt5完成的PDF拆分功能,本文介紹的pdf拆分功能還有一些待完善地方,例如可增加預(yù)覽功能,實現(xiàn)每頁預(yù)覽,以及如何實現(xiàn)多條件拆分,需要的朋友可以參考下
    2022-06-06
  • python開發(fā)之字符串string操作方法實例詳解

    python開發(fā)之字符串string操作方法實例詳解

    這篇文章主要介紹了python開發(fā)之字符串string操作方法,以實例形式較為詳細的分析了Python針對字符串的轉(zhuǎn)義、連接、換行、輸出等操作技巧,需要的朋友可以參考下
    2015-11-11
  • python?pycharm安裝第三方包失敗(使用pip安裝失敗)的解決方案

    python?pycharm安裝第三方包失敗(使用pip安裝失敗)的解決方案

    這篇文章主要給大家介紹了關(guān)于python?pycharm安裝第三方包失敗(使用pip安裝失敗)的解決方案,文中將可能遇到的幾種情況都進行了分析并給出了詳細的解決方案,需要的朋友可以參考下
    2023-11-11
  • Python創(chuàng)建exe運行器和截圖工具的示例詳解

    Python創(chuàng)建exe運行器和截圖工具的示例詳解

    本文我們將探討如何使用Python和wxPython創(chuàng)建一個強大而實用的桌面應(yīng)用程序,可以遍歷指定文件夾中的所有EXE文件,感興趣的小伙伴可以了解一下
    2024-10-10

最新評論

新田县| 甘泉县| 南川市| 枣阳市| 苍南县| 黑水县| 化州市| 阿瓦提县| 榆林市| 扶沟县| 滨州市| 巍山| 茶陵县| 孟州市| 泰顺县| 潢川县| 永德县| 高阳县| 东宁县| 南阳市| 靖江市| 湖南省| 宜城市| 连云港市| 新巴尔虎右旗| 滦平县| 紫云| 泸州市| 花垣县| 沾化县| 固原市| 永仁县| 慈溪市| 澄江县| 柘城县| 于田县| 南通市| 玉田县| 元朗区| 婺源县| 油尖旺区|