【问题标题】:Need help to make asynchronous version of "loop for"需要帮助来制作“loop for”的异步版本
【发布时间】:2016-03-20 12:06:13
【问题描述】:

解析来自 Wikipedia 的数据需要很长的时间。我想做而不是一个线程\进程,至少5个。谷歌搜索后我发现在Python 3.5中有async for

下面是当前“同步”代码的“非常短”版本,用于显示整个过程(使用 cmets 可以快速了解代码的作用)。

def update_data(region_id=None, country__inst=None, upper_region__inst=None):
    all_ids = []

    # Get data about countries or regions or subregions
    countries_or_regions_dict = OSM().get_countries_or_regions(region_id)

    # Loop that I want to make async
    for osm_id in countries_or_regions_dict:
        names = countries_or_regions_dict[osm_id]['names']

         if 'wiki_uri' in countries_or_regions_dict[osm_id]:
            wiki_uri = countries_or_regions_dict[osm_id]['wiki_uri']

            # PARSER: From Wikipedia gets translations of countries or regions or subregions
            translated_names = Wiki().get_translations(wiki_uri, osm_id)

            if not region_id:  # Means it is country
                country__inst = Countries.objects.update_or_create(osm_id=osm_id,
                                                                   defaults={**countries_regions_dict[osm_id]})[0]

            else: # Means it is region\subregion (in case of recursion)
                upper_region__inst = Regions.objects.update_or_create(osm_id=osm_id,
                                                                      country=country__inst,
                                                                      region=upper_region__inst,
                                                                      defaults={**countries_regions_dict[osm_id]})[0]
            # Add to DB translated names from wiki
            for lang_code in names:
                ###

            # RECURSION: If country has regions or region has subregions, start recursion
            if 'divisions' in countries_or_regions_dict[osm_id]:
                regions_list = countries_or_regions_dict[osm_id]['divisions']

                for division_id in regions_list:
                    all_regions_osm_ids = update_osm(region_id=division_id, country__inst=country__inst,
                                                              upper_region__inst=upper_region__inst)

                    all_ids += all_regions_osm_ids

    return all_ids

我意识到我需要将def update_data 更改为async def update_data 并相应地将for osm_id in countries_or_regions_dict 更改为async for osm_id in countries_or_regions_dict

但我找不到在我的情况下是否有必要使用get_event_loop() 以及在哪里使用的信息,以及如何\在哪里指定可以同时运行多少次循环迭代?有人可以帮我使loop for 异步吗?

【问题讨论】:

    标签: django python-3.x asynchronous python-asyncio


    【解决方案1】:

    asyncio 模块不创建多个线程/进程,它在一个线程、一个进程中运行代码,但可以处理带有 I/O 块的情况(如果您以特殊方式编写代码)。 Read,什么时候应该使用asyncio

    只要您的代码具有同步特性,我建议您使用线程而不是 asyncio。创建ThreadPoolExecutor并使用它在多个线程中解析Wiki。

    【讨论】:

    • 您的帖子促使我阅读了很多 :) 现在我明白了,asyncio 在一个线程\进程中完成所有事情。你能澄清一些事情吗? 1)ThreadPoolExecutor(TPE)可以启动不同的线程,但是在给定的时间只能使用一个线程,所以它类似于asyncio。我对吗? 2)在我的情况下,我可以使用这两种方法(因为两者都解决了 IO 绑定问题,在我的情况下是“解析”),但是 TPE 更容易,因为我只需要对我的代码进行少量更改?
    • 3) 方法“get_translations”使用“请求”。如果“请求”需要资源来下载页面,而 TPE 只使用一个线程,那么好处在哪里? IO 操作的执行是否超出了线程的范围?
    • @TitanFighter, 1) 是 2) 是 3) 您应该在线程执行器中运行多个“get_translations”。 TPE 将使用多个线程。虽然一次只能运行其中一个,但一旦它面临 I/O 操作,它就会将控制权转移到另一个线程,而不是浪费时间等待 I/O 将完成。这是因为网络 I/O 操作本身是异步的。阅读有关 I/O 的链接:stackoverflow.com/a/16528847/1113207 您还可以阅读这篇带有代码示例的文章(尤其是“入门”及以下内容):chriskiehl.com/article/parallelism-in-one-line
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    相关资源
    最近更新 更多