Python 3.6 asyncio-从未检索到任务异常-任务产出不良:200

时间:2019-03-23 16:05:12

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

我已经阅读了其他问题和答案,但仍然无法弄清我在做什么错。

我正在尝试使用ES的asyncio实现(https://github.com/elastic/elasticsearch-py-async)在Python 3.6中创建Elasticsearch 6.x生产者,并且在它工作时(记录已成功推送到ES中),我得到了{{1} }和Task Exception was never retried错误。我认为它们都是相同的问题造成的,而一个可能是导致另一个的原因?

我正在使用以下模块:

Task got bad yield: 200

下面是我的代码:

python 3.6
elasticsearch=6.3.1
elasticsearch-async=6.2.0
boto3=1.9.118

以下是我每次致电import json import boto3 import logging import os import gzip import asyncio from elasticsearch import RequestsHttpConnection from elasticsearch_async import AsyncElasticsearch from assume_role_aws4auth import AssumeRoleAWS4Auth import time logger = logging.getLogger() logger.setLevel(logging.INFO) # Operating constants MAX_RECORDS_IN_BATCH = 500 MAX_BATCH_SIZE = 10000000 # boto3 clients credentials = boto3.Session().get_credentials() awsauth = AssumeRoleAWS4Auth(credentials, 'us-east-1', 'es') cloudwatch_client = boto3.client('cloudwatch') s3_resource = boto3.resource('s3') event_loop = asyncio.get_event_loop() es_client = AsyncElasticsearch(hosts=['https://ES_HOST'], http_compress=True, http_auth=awsauth, use_ssl=True, verify_certs=True, connection_class=RequestsHttpConnection, loop=event_loop) def lambda_handler(filename, context): event_loop.run_until_complete(process(filename)) pending = asyncio.Task.all_tasks() event_loop.run_until_complete(asyncio.gather(*pending)) async def process(filename: str): for action_chunk in read_chunk(filename, MAX_BATCH_SIZE, MAX_RECORDS_IN_BATCH): try: resp = asyncio.ensure_future(es_client.bulk(body=action_chunk, index='index', doc_type='type', _source=False)) await asyncio.sleep(.1) except Exception as ex: logger.error(ex) def read_chunk(file_path: str, max_batch_size: int, max_records: int): actions: str = '' actions_size: int = 0 num_actions: int = 0 with gzip.open(file_path, 'rt') as f: for line in f: request = json.dumps(dict({'index': dict({})})) + '\n' + line + '\n' request_size = len(request.encode('utf-8')) # Check to see if this record will put us over the limits if (actions_size + request_size) > max_batch_size or num_actions == max_records: yield actions actions = '' num_actions = 0 actions_size = 0 # Add the record actions += request num_actions += 1 actions_size += request_size if actions != '': yield actions if __name__ == '__main__': lambda_handler('/path/to/file', None) 时遇到的错误:

es_client.bulk

有人可以告诉我我在做什么错吗?另外,如果有什么我可以做的更好/更有效的事情,我很想听听。我想使用Helpers软件包,但没有异步实现。

1 个答案:

答案 0 :(得分:1)

我不确定是否是问题所在,但是这可能会发生。

您可以在process()协程中创建多个任务,但不要存储对它们的引用。这可能会导致问题:在显式检索它们的结果之前,有些任务是garbage collected。如果发生这种情况,asyncio warns请您注意情况。

要解决此问题,您应该存储所有创建的任务,并确保等待所有任务:

tasks = []

# ...

async def process(filename: str):
    # ...
    task = asyncio.ensure_future(...)
    tasks.append(task)
    # ...


def lambda_handler(filename, context):
    # ...
    event_loop.run_until_complete(asyncio.gather(*tasks ))

如果我的猜测是正确的,您可能会看到RuntimeError('Task got bad yield: 200',)处出现了lambda_handler。您可以检索所有异常,而无需引发将return_exceptions=True参数传递给asyncio.gather的异常。这样,您可以避免发出警告(但不能避免这些异常首先发生的根本原因)。

很抱歉,除了这里没有其他帮助。

更新:

我更改了原始版本的答案修正错误。