Python 多執行緒 asyncio 十六

2022-07-09 15:30:15 字數 4901 閱讀 9607

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,time

def 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 multiprocessing

def 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()  如果事件迴圈已關閉,返回true
4.3 協程

協程不是程序、也不是執行緒,它是使用者空間排程完成併發處理的方式。(同一執行緒內交替執行其實也是偽併發)

併發指的是在一段時間內做了多少、並行指的是同一時刻有多少同時執行。

程序、執行緒由作業系統完成排程,而協程是執行緒內完成排程。它不需要更多的執行緒,也就沒有多執行緒切換帶來的開銷。

協程是非搶占式排程,只有乙個協程主動讓出控制權,另乙個協程才會被排程。

協程也不需要鎖機制,因為是在同一執行緒中執行。

多cpu下,可以使用多執行緒和協程配合,既能程序併發又能發揮協程在單執行緒中的優勢。

python中協程是基於生成器的。

4.4 協程的使用

4.4.1 python3.4中使用@asyncio.coroutine 、 yield from

#asyncio python3.4

import 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.5

import 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分鐘。多執行緒的情況下,程式就會同時進行多個任務,雖然在同一時刻也只能執行某個任...