天天看點

python異步

協程

微線程,纖程 -- Coroutine

子程式(函數) -- 所有語言中都是層級調用,子程式調用是一通過棧實作的,一個線程就是執行一個子程式。

子程式調用是明确的,一個入口,一次傳回。

協程看上去像子程式,但在執行過程中可中斷。有點像執行多線程,但是它是一個線程執行。

協程比多線程的優勢:極高的執行效率,沒有線程切換的開銷;沒有線程的鎖機制。

使用協程利用多CPU的方式:多程序+協程

python對協程的支援通過generator實作。

通過for疊代,不斷調用next()函數擷取由yield傳回的下一個值。

python的yield不但可以傳回一個值,還可以接收調用者發出的參數。

生産者消費者通過yield的執行個體:

<code>def</code> <code>consumer():</code>

<code>    </code><code>r</code><code>=</code><code>''</code>

<code>    </code><code>while</code> <code>True</code><code>:</code>

<code>        </code><code>n </code><code>=</code> <code>yield</code> <code>r</code>

<code>        </code><code>if</code> <code>not</code> <code>n:</code>

<code>            </code><code>return</code>

<code>        </code><code>print</code><code>(</code><code>'[CONSUMER] Consuming %s...'</code> <code>%</code> <code>n)</code>

<code>        </code><code>r </code><code>=</code> <code>'200 OK'</code>

<code>        </code> 

<code>def</code> <code>produce(c):</code>

<code>    </code><code>c.send(</code><code>None</code><code>)</code>

<code>    </code><code>n </code><code>=</code> <code>0</code>

<code>    </code><code>while</code> <code>n &lt; </code><code>5</code><code>:</code>

<code>        </code><code>n </code><code>=</code> <code>n</code><code>+</code><code>1</code>

<code>        </code><code>print</code><code>(</code><code>'[PRODUCER] Producing %s...'</code> <code>%</code> <code>n)</code>

<code>        </code><code>r </code><code>=</code> <code>c.send(n)</code>

<code>        </code><code>print</code><code>(</code><code>'[PRODUCER] Consumer return: %s'</code> <code>%</code> <code>r)</code>

<code>    </code><code>c.close()</code>

<code>    </code> 

<code>c </code><code>=</code> <code>consumer()</code>

<code>produce(c)</code>

asyncio的程式設計模型就是一個消息循環。

實作異步IO -- 從asyncio子產品中擷取一個eventloop的引用,然後把需要執行的協程扔到eventloop中執行。

<code>import</code> <code>asyncio</code>

<code>@asyncio</code><code>.coroutine</code>

<code>def</code> <code>hello():</code>

<code>    </code><code>print</code><code>(</code><code>"hello, world!"</code><code>)</code>

<code>    </code><code># 異步調用 asyncio.sleep(1)</code>

<code>    </code><code>r </code><code>=</code> <code>yield</code> <code>from</code> <code>asyncio.sleep(</code><code>1</code><code>)</code>

<code>    </code><code>print</code><code>(</code><code>"hello again!"</code><code>)</code>

<code># 擷取eventloop        </code>

<code>loop </code><code>=</code> <code>asyncio.get_event_loop()</code>

<code># 執行conroutine</code>

<code>loop.run_until_complete(hello())</code>

<code>loop.close()</code>

async/await

async和await是針對coroutine的新文法,隻需要做兩部簡單的替換。

把@asyncio.coroutine替換為async

把yield from 替換為await

<code>async </code><code>def</code> <code>hello():</code>

<code>    </code><code>print</code><code>(</code><code>"hello world!"</code><code>)</code>

<code>    </code><code>r </code><code>=</code> <code>await asyncio.sleep(</code><code>1</code><code>)</code>

aiohttp

asyncio實作了TCP、UDP、SSL協定,aiohttp基于asyncio實作的http架構。

一個aiohttp實作的http伺服器。分别處理以下URL:

/ -- 傳回b'&lt;h1&gt;Index&lt;/h1&gt;'

/hello/{name} -- 根據URL參數傳回文本hello,%s!

<code>from</code> <code>aiohttp </code><code>import</code> <code>web</code>

<code>async </code><code>def</code> <code>index(request):</code>

<code>    </code><code>await asyncio.sleep(</code><code>0.5</code><code>)</code>

<code>    </code><code>return</code> <code>web.Response(body</code><code>=</code><code>b</code><code>'&lt;h1&gt;Index&lt;/h1&gt;'</code><code>)</code>

<code>async </code><code>def</code> <code>hello(request):</code>

<code>    </code><code>text</code><code>=</code><code>'&lt;h1&gt;hello, %s!&lt;/h1&gt;'</code> <code>%</code> <code>request.match_info[</code><code>'name'</code><code>]</code>

<code>    </code><code>return</code> <code>web.Response(body</code><code>=</code><code>text.encode(</code><code>'utf-8'</code><code>))</code>

<code>async </code><code>def</code> <code>init(loop):</code>

<code>    </code><code>app </code><code>=</code> <code>web.Application(loop</code><code>=</code><code>loop)</code>

<code>    </code><code>app.router.add_route(</code><code>'GET'</code><code>, </code><code>'/'</code><code>, index)</code>

<code>    </code><code>app.router.add_route(</code><code>'GET'</code><code>, </code><code>'/hello/{name}'</code><code>, hello)</code>

<code>    </code><code>srv </code><code>=</code> <code>await loop.create_server(app.make_handler(), </code><code>'127.0.0.1'</code><code>, </code><code>8000</code><code>)</code>

<code>    </code><code>print</code><code>('Server started at </code>

<code>    </code><code>return</code> <code>srv</code>

<code>loop.run_until_complete(init(loop))</code>

<code>loop.run_forever()</code>

<code></code>

本文轉自ting2junshui51CTO部落格,原文連結:http://blog.51cto.com/ting2junshui/1753737 ,如需轉載請自行聯系原作者