2017-02-21 54 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 
相关问题