如何调试aiohttp慢速异步

时间:2019-01-30 11:36:07

标签: python python-3.x python-asyncio aiohttp

我最近一直在使用asyncio模块。以下是我为发送一些并行请求而想出的代码,这些请求在我的笔记本电脑(Mac OS)上似乎可以正常工作,但在另一台计算机(Ubuntu 18.04)上却运行缓慢。在运行缓慢的计算机中(Ubuntu 18.04),我再次在其中安装了virtualbox vm,同时安装了Ubuntu 18.04,令我惊讶的是,该代码在该处运行得很好。我在Ubuntu机器中有多个版本的python,并且正在尝试以3.7.2运行。我不确定如何在这里缩小问题的范围。如果有人可以帮助我,那就太好了。

我确定这不是网络问题。在Ubuntu物理机中,此代码大约需要130秒才能完成。但是在可以正常工作的Ubuntu VM内,只需不到5秒的时间。

import aiohttp
import asyncio
import ssl
import time
from bs4 import BeautifulSoup


async def get_app_updated_date(html_content):
    soup = BeautifulSoup(html_content, 'lxml')
    section_titles_divs = [x for x in soup.select('div.hAyfc div.BgcNfc')]

    title_normalization = {
        'Updated': 'updated',
    }

    data = {
        'updated': None,
    }

    for title_div in section_titles_divs:
        section_title = title_div.string
        if section_title in title_normalization:
            title_key = title_normalization[section_title]
            value_div = title_div.next_sibling.select_one('span.htlgb')
            value = value_div.text
            data[title_key] = value
    return data


async def fetch(session, url, app_id):
    print(f'Fetching information for {app_id}')
    async with session.get(url, params={'id': app_id}, ssl=ssl.SSLContext()) as response:
        html_resp = await response.text()
        app_lastupdated_date = await get_app_updated_date(html_resp)
        return {app_id: app_lastupdated_date}


async def main():
    url = 'https://play.google.com/store/apps/details'
    app_list = ['com.google.android.youtube',
                'com.whatsapp',
                'com.instagram.android',
                'com.google.android.apps.maps',
                'com.kiloo.subwaysurf',
                'com.halfbrick.fruitninjafree',
                'com.adobe.reader',
                'org.mozilla.firefox',
                'com.zeptolab.ctr.ads',
                'com.fingersoft.hillclimb']
    async with aiohttp.ClientSession() as session:
        url_requests = [fetch(session, url, app_id) for app_id in app_list]
        print(url_requests)
        results = await asyncio.gather(*url_requests)
        for r in results:
            print(r)
        print(f'Result size  = {len(results)}')


if __name__ == '__main__':
    start_time = time.time()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    print(f'Script execution completed in: {time.time() - start_time} seconds')

更新: 按照建议,附上我的探查器报告。无法理解行话。同样,在此论坛中寻求人们的专业知识。

profiler_screenshot_1 profiler_screenshot_2

1 个答案:

答案 0 :(得分:1)

我建议您至少缩小范围。在您的IDE中使用profiling模块或探查器(即Pycharm提供了很好的工具)来了解有问题的功能。

但是IMO,这实际上看起来像是网络问题,因为在裸机上的Ubuntu下运行是:

  • python环境
  • 事件循环实现
  • 对系统软件包的绑定
  • ubuntu网络(包括DNS解析器)

VM中的Ubuntu是:

  • python环境
  • 事件循环实现
  • 对系统软件包的绑定
  • 从VM到主机系统的桥接网络(取决于VM的设置)
  • Windows网络(包括DNS解析器)