3.4版本之後加入標準庫。html
Asyncio底層基於selectors,看似庫,其實就是框架,包含異步IO、時間循環、協程、任務等內容。web
def a(x=3):
for x in range(x):
print(x)
def b(x=3):
for x in range(x):
print(x)
a()
b()
上例子中函數調用是串行,不是並行。能夠利用方法進行改變。chrome
1)利用生成器函數session
def a(x=3):
for x in range(x):
print(x)
yield
def b(x=3):
for x in range(x):
print(x)
yield
x1 = a()
y = b()
for i in range(3):
next(x1)
next(y)
2)多線程多線程
import time
import threading
def a(x=3):
for x in range(x):
time.sleep(1)
print(x)
def b(x=3):
for x in range(x):
time.sleep(1)
print(x)
threading.Thread(target=a,name='a').start()
threading.Thread(target=b,name='b').start()
3)利用multiprocessing庫,也是多線程併發
import time
import multiprocessing
def a(x=3):
for x in range(x):
time.sleep(1)
print(x)
def b(x=3):
for x in range(x):
time.sleep(1)
print(x)
if __name__ == '__main__':
multiprocessing.Process(target=a,name='a').start()
multiprocessing.Process(target=b,name='b').start()
生成器函數,真並行。app
生成器在用戶空間完成的切換。調度不是操做系統的進程、線程。兩個函數都有機會執行。框架
Yield本意是讓出,讓出線程執行的權限,讓出控制權限。異步
必須有循環,沒有循環就不可以交替執行。async
事件循環是asyncio提供的核心運行機制。
Column |
Column |
Asyncio.get_event_loop() |
返回一個事件循環對象,是asyncio.Baseeventloop的實例 |
Abstracteventloop.stop() |
中止運行事件循環 |
Abstracteventloop.run_forever() |
一直運行直到stop() |
Abstracteventloop.run_until_complete(future) |
運行直至future對象運行完 |
Abstracteventloop.close() |
關閉事件循環 |
Abstracteventloop.is_running() |
返回事件循環的是否運行 |
1)不是進程,也不是線程,是用戶空間調度的完成併發處理的方式。是在用戶空間內部完成的。
2)進程、線程是操做系統完成調度,而協程是線程內完成調度,不須要更多的線程,也沒有多線程切換帶來的開銷。
3)協程是非搶佔式調度,只有協程主動讓出控制權,另外一個協程纔會被調度。
4)協程不須要使用鎖機制,由於是在同一個線程中執行的。
5)多CPU下,可使用多進程和協程配合下,既能進程並行又能發揮協程在單線程中的優點。
6)Python中協程是基於生成器的。
線程和進程是操做系統內完成的。
Coroutine協程;
await:等待,至關於yield form。
import asyncio
@asyncio.coroutine
def sleep(x):
for i in range(3):
print('sleep {}'.format(i))
yield from asyncio.sleep(3)
loop = asyncio.get_event_loop()
loop.run_until_complete(sleep(3))
loop.close()
將生成器函數轉換爲協程函數,就能夠在循環中執行了。
3.5版本後,Python提供關鍵字async,await,在語言上原生支持協程。
import asyncio
async def sleep(x):
for i in range(3):
print('sleep{}'.format(i))
await asyncio.sleep(x)
loop = asyncio.get_event_loop()
loop.run_until_complete(sleep(3))
loop.close()
sleep 0
sleep 1
sleep 2
Async 得分用來定義協程函數,iscoroutinefunction()返回True,協程函數中能夠不包含await,async關鍵字,但不能上使用yield關鍵字。
如同生成器函數調用返回生成器對象同樣,協程函數調用也會返回一個對象成爲協程對象,iscoroutine()返回True。
import asyncio
import threading
async def sleep(x):
for i in range(3):
print('sleep{}'.format(i))
await asyncio.sleep(x)
async def showthread(x):
for i in range(3):
print(threading.enumerate())
await asyncio.sleep(2)
loop = asyncio.get_event_loop()
tasks = [sleep(3),showthread(3)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
協程版本
import asyncio
import threading
@asyncio.coroutine
def a():
for x in range(3):
print('a.x',x)
yield
@asyncio.coroutine
def b():
for i in range(3):
print('b.x',i)
yield
print(asyncio.iscoroutinefunction(a))
print(asyncio.iscoroutinefunction(b))
loop = asyncio.get_event_loop()
tasks = [a(),b()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
Tasks,任務列表。
下面是執行的;
新的語法。
import asyncio
async def handle(reader,writer):
while True:
data = await reader.read(1024)
print(dir(reader))
print(dir(writer))
client = writer.get_extra_info('peername')
message = '{}you mesg {}'.format(client,data.decode()).encode()
writer.writer(message)
await writer.drain()
loop = asyncio.get_event_loop()
ip = '127.0.0.1'
port = 8080
crt = asyncio.start_server(handle,ip,port,loop=loop)
server = loop.run_until_complete(crt)
print(server)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.close()
loop.close()
安裝pip install aiohttp
寫http服務。
http server
from aiohttp import web
async def indexhandle(request:web.Request):
return web.Response(text=request.path,status=201)
async def handle(request:web.Request):
print(request.match_info)
print(request.query_string)
return web.Response(text=request.match_info.get('id','0000'),status=200)
app = web.Application() #默認端口和地址。
app.router.add_get('/',indexhandle) #請求來了找處理函數。
app.router.add_get('/{id}',handle)
web.run_app(app,host='127.0.0.1',port=8080)
======== Running on http://127.0.0.1:8080 ========
(Press CTRL+C to quit)
<MatchInfo {'id': 'favicon.ico'}: <ResourceRoute [GET] <DynamicResource /{id}> -> <function handle at 0x00000044F1494730>>
import asyncio
from aiohttp import ClientSession
async def get_html(url:str):
async with ClientSession() as session: #with是上下文
async with session.get(url) as res: #session是保持會話,get獲得一個網頁。
print(res.status) # 打印狀態碼
print(await res.text()) # 提取文本內容。首頁都是同步加載,裏面異步加載請求。
url = 'http://www.magedu.com'
loop = asyncio.get_event_loop()
loop.run_until_complete(get_html(url))
loop.close()
200
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width">
<meta name="format-detection" content="telephone=no">