Как перебрать итератор неопределенной длины с помощью asyncio - PullRequest
1 голос
/ 23 апреля 2019

Я загружаю список ключей из корзины S3 и не знаю, сколько их. Я остановил свой процесс после 300 000 ключей и 5 минут, и я хотел бы использовать asyncio (в этом я только начинающий пользователь. Я использовал его, чтобы загрузить предварительно определенный список URL-адресов один раз), чтобы ускорить процесс.

Моя текущая синхронная функция работает следующим образом:

def get_keys(s3, bucket_name, prefix):
    # s3 previously defined by boto3.resource('s3') with AWS key and secret key as kwargs
    bucket = s3.Bucket(bucket_name)
    keys = []
    for item in bucket.objects.filter(Prefix=prefix):
        keys.append(item.key)
    return keys

1 Ответ

1 голос
/ 23 апреля 2019

Асинсио здесь вам не поможет, к сожалению.

Во-первых и самое главное, boto3 не осведомлен об асинхронности; он не знает, как использовать цикл asyncio для создания соединений, он просто работает в одном синхронном потоке. (Конечно, вы можете использовать несколько потоков или multiprocessing подпроцессов для выполнения запросов, но смотрите ниже, почему это тоже не поможет.)

Основной вызов функции S3 .objects.filter делает list_objects_v2, что позволяет составить один список до 1000 ключей на запрос. Если возвращено более 1000 ключей, значение результата будет содержать IsTruncated=True и NextContinuationToken, которые можно использовать для получения следующей страницы результатов.
Вы не можете предсказать последовательность ContinuationToken с, поэтому вы не можете распараллелить вещи по токену продолжения.

Если вы знаете больше знаете о префиксах, которые вы ищете, вы можете распараллелить их, например - если вы ищете префикс 'aaa/bbb', и вы знаете его ключи это может быть aaa/bbb/0..., aaa/bbb/1..., aaa/bbb/2..., вы можете выполнять эти запросы параллельно, чтобы повысить производительность.

...