asyncio
該模組是3.4版本加入的新功能。
先來看乙個例子:
def a():for x in range(3):
print('a.x', x)
def b():
for x in 'abc':
print('b.x', x)
a()b()
#執行結果:
a.x 0
a.x 1
a.x 2
b.x a
b.x b
b.x c
這個例子是乙個典型的序列程式,兩個函式呼叫是在主線程中順序執行。
有以下幾種方法可以讓這段程式改為並行:
1. 生成器
2. 多執行緒
3. 多程序
4. 協程
1)生成器方法:
def a():for x in range(3):
yield x
def b():
for x in 'abc':
yield x
m = a()
n = b()
for _ in range(3):
print(next(m))
print(next(n))
#執行結果:0a
1b2c
使用生成器來實現交替執行。這兩個函式都有機會執行,這樣的排程不是作業系統的程序、執行緒完成的,而是使用者自己設計的。
2)多執行緒方法:
import threading,timedef a():
for x in range(3):
time.sleep(0.0001)
print('a.x',x)
def b():
for x in 'abc':
time.sleep(0.0001)
print('b.x',x)
threading.thread(target=a).start()
threading.thread(target=b).start()
#執行結果:
a.x 0
b.x a
a.x 1
b.x b
a.x 2
b.x c
主要使用sleep函式強制切換來實現偽並行。
3)多程序方式:
import multiprocessingdef a():
for x in range(3):
print('a.x',x)
def b():
for x in 'abc':
print('b.x',x)
if __name__ == '__main__':
multiprocessing.process(target=a).start()
multiprocessing.process(target=b).start()
#執行結果:
a.x 0
a.x 1
a.x 2
b.x a
b.x b
b.x c
多程序方式才是真正的並行。
4)協程方法:
協程,需要使用到 asyncio 標準庫,是python3.4版本加入的新功能,底層基於selectors實現,包括非同步io、事件迴圈、協程等內容。
事件迴圈:
事件迴圈是asyncio提供的核心執行機制。
程式開啟乙個無限的迴圈,使用者會把一些函式註冊到事件迴圈上。當滿足事件發生的時候,呼叫相應的協程函式。
4.1 事件迴圈基類
asyncio.baseeventloop 這個類是乙個實現細節,它是asyncio.abstracteventloop的子類,不可以直接使用
asyncio.abstracteventloop 事件迴圈的抽象基類,這個類是是執行緒不安全的4.2 執行事件迴圈
asyncio.get_event_loop() 返回乙個事件迴圈物件,是asyncio.baseeventloop的例項
asyncio.abstracteventloop.stop() 停止執行事件迴圈
asyncio.abstracteventloop.run_forever() 一直執行,直到呼叫stop()
asyncio.abstracteventloop.run_until_complete(future) 執行直到future物件執行完成,返回結果
asyncio.abstracteventloop.close() 關閉事件迴圈
asyncio.abstracteventloop.is_running() 返回事件迴圈的執行狀態
asyncio.abstracteventloop.is_closed() 如果事件迴圈已關閉,返回true4.3 協程
協程不是程序、也不是執行緒,它是使用者空間排程完成併發處理的方式。(同一執行緒內交替執行其實也是偽併發)
併發指的是在一段時間內做了多少、並行指的是同一時刻有多少同時執行。
程序、執行緒由作業系統完成排程,而協程是執行緒內完成排程。它不需要更多的執行緒,也就沒有多執行緒切換帶來的開銷。
協程是非搶占式排程,只有乙個協程主動讓出控制權,另乙個協程才會被排程。
協程也不需要鎖機制,因為是在同一執行緒中執行。
多cpu下,可以使用多執行緒和協程配合,既能程序併發又能發揮協程在單執行緒中的優勢。
python中協程是基於生成器的。
4.4 協程的使用
4.4.1 python3.4中使用@asyncio.coroutine 、 yield from
#asyncio python3.4import asyncio
@asyncio.coroutine
def foo(x): #生成器函式上面加了協程裝飾器之後就轉化成協程函式
for i in range(3):
print('foo {}'.format(i))
yield from asyncio.sleep(x) #呼叫另乙個生成器物件
loop = asyncio.get_event_loop() #獲得乙個時間迴圈
loop.run_until_complete(foo(1)) #傳入乙個生成器物件的呼叫
loop.close()
#執行結果:
foo 0
foo 1
foo 2
[finished in 3.3s]
此例子在乙個生成器函式加了協程裝飾器之後,該生成器函式就轉化成了協程函式。
4.4.2 python3.5中使用關鍵字 async def 、 await ,在語法上原生支援協程
#asyncio python3.5import asyncio
async def foo(x): #非同步定義,協程定義
for i in range(3):
print('foo {}'.format(i))
await asyncio.sleep(x) #不可以出現yield,使用await替換
print(asyncio.iscoroutinefunction(foo))
loop = asyncio.get_event_loop()
loop.run_until_complete(foo(1)) #傳入乙個協程物件的呼叫
loop.close()
#執行結果:
true
foo 0
foo 1
foo 2
[finished in 3.3s]
async def 用來定義協程函式,iscoroutinefunction(func)判斷func函式是否是乙個協程函式。協程函式中可以不包含await、async關鍵字,但不能使用yield關鍵字。
其它語法:async with,支援上下文的協程
4.4.3 coroutine asyncio.wait(futures, *, loop=none, timeout=none, return_when=all_completed)
等待futures序列中的協程物件執行完成,futures序列不可以為空。
timeout可以用於控制返回前等待的最大秒數,秒數可以是int或浮點數,如果未指定timeout,則無限制。
#wait多個協程物件import asyncio
@asyncio.coroutine
def a():
for i in range(3):
print('a.x',i)
yield
@asyncio.coroutine
def b():
for i in range(3):
print('b.x',i)
yield
loop = asyncio.get_event_loop()
tasks = [a(),b()]
loop.run_until_complete(asyncio.wait(tasks)) #傳入乙個協程物件序列
loop.close()
#執行結果:
b.x 0
a.x 0
b.x 1
a.x 1
b.x 2
a.x 2
[finished in 0.3s]
總結:傳統的多執行緒、多程序都是系統完成排程,而協程是在程序中的執行緒內由使用者空間排程完成併發處理,主要依靠生成器來實現交替排程。
python3.4中使用@asyncio.coroutine、yield from呼叫另乙個生成器物件
python3.5中使用關鍵字 async def 和 await,且不可以出現yield關鍵字。
python多執行緒 python多執行緒
通常來說,多程序適用於計算密集型任務,多執行緒適用於io密集型任務,如網路爬蟲。關於多執行緒和多程序的區別,請參考這個 下面將使用python標準庫的multiprocessing包來嘗試多執行緒的操作,在python中呼叫多執行緒要使用multiprocessing.dummy,如果是多程序則去掉...
python多執行緒詳解 Python多執行緒詳解
前言 由於最近的工作中一直需要用到python去處理資料,而在面對大量的資料時,python多執行緒的優勢就展現出來了。因而藉此機會,盡可能詳盡地來闡述python多執行緒。但對於其更底層的實現機制,在此不做深究,僅是對於之前的一知半解做個補充,也希望初學者能夠通過這篇文章,即便是照葫蘆畫瓢,也能夠...
python程式多執行緒 PYTHON多執行緒
在單執行緒的情況下,程式是逐條指令順序執行的。同一時間只做乙個任務,完成了乙個任務再進行下乙個任務。比如有5個人吃飯,單執行緒一次只允許乙個人吃,乙個人吃完了另乙個人才能接著吃,假如每個人吃飯都需要1分鐘,5個人就需要5分鐘。多執行緒的情況下,程式就會同時進行多個任務,雖然在同一時刻也只能執行某個任...