2017-02-21 52 views
1

我想ayncio和使用coroutine不與線程相關的,因爲coroutine是一種「線」下程序的調度運行的,所以應該只有1個線程運行每個過程。但是,當我在Making 1 million requests with python-aiohttp跑的例子,代碼如下圖所示:爲什麼ASYNCIO使與aiohttp請求仍然使用線程的

# modified fetch function with semaphore 
import random 
import asyncio 
from aiohttp import ClientSession 

async def fetch(url, session): 
    async with session.get(url) as response: 
     delay = response.headers.get("DELAY") 
     date = response.headers.get("DATE") 
     print("{}:{} with delay {}".format(date, response.url, delay)) 
     return await response.read() 


async def bound_fetch(sem, url, session): 
    # Getter function with semaphore. 
    async with sem: 
     await fetch(url, session) 


async def run(r): 
    url = "http://localhost:8080/{}" 
    tasks = [] 
    # create instance of Semaphore 
    sem = asyncio.Semaphore(1000) 

    # Create client session that will ensure we dont open new connection 
    # per each request. 
    async with ClientSession() as session: 
     for i in range(r): 
      # pass Semaphore and session to every GET request 
      task = asyncio.ensure_future(bound_fetch(sem, url.format(i), session)) 
      tasks.append(task) 

     responses = asyncio.gather(*tasks) 
     await responses 

number = 10000 
loop = asyncio.get_event_loop() 

future = asyncio.ensure_future(run(number)) 
loop.run_until_complete(future) 

使用Windows'資源監視器,我發現代碼1個過程中創建25個線程。

回答

1

Python的標準庫包含一個名爲threading的模塊,該模塊允許使用Thread實例同時運行python代碼。 asyncioaiohttp不使用threading模塊進行操作。

Python本身可能會使用OS(低級別)線程作爲實現細節 - 但這可能會在不同的平臺和版本之間發生變化。例如,Windows 10中python 3.6.0的簡單print('hello world'); s = input()的操作系統線程數爲3.

檢出https://github.com/python/cpython/blob/3.6/Lib/asyncio/windows_events.py以查找可能在Windows中啓動操作系統線程的線索。

0

aiohttp庫默認使用線程進行並行DNS解析,以便不阻止IO循環,請參閱aiohttp/resolver.py。如果你想異步DNS查找,你需要安裝python包aiodns,這反過來使用pycares

那麼你可以這樣做:

async def fetch(url): 
    resolver = aiohttp.AsyncResolver() 
    connector = aiohttp.TCPConnector(resolver=resolver, family=socket.AF_INET) 
    async with aiohttp.ClientSession(connector=connector) as session: 
     async with session.get(url) as resp: 
      if resp.status == 200: 
       print("success!") 

如果你想設置AsyncResolver作爲一個全球性默認情況下,這個工作對我來說與aiohttp 2.2.3:

import aiohttp.resolver 
aiohttp.resolver.DefaultResolver = aiohttp.resolver.AsyncResolver 
相關問題