Копия файла из одного местоположения s3 в другое не работает после запроса athena boto3 - PullRequest
1 голос
/ 09 апреля 2019

Я использую boto3 для запроса результатов из Афины.Они работают нормально.Я снова использую boto3, чтобы скопировать файл из одной корзины s3 в другую, но он говорит, что не может найти файл.Я не могу найти решение.Пожалуйста, помогите!

Когда я захожу на консоль s3, я вижу файл, но boto3 не может его найти.

import boto3

athena = boto3.client('athena')
s3 = boto3.resource('s3')
BUCKET_NAME = 'bucket1'
bucket = s3.Bucket(BUCKET_NAME)


query = 'SELECT * FROM "db"."table" limit 2'
response = athena.start_query_execution(QueryString=query, QueryExecutionContext={
            'Database': 'db'
            }, ResultConfiguration={
            'OutputLocation': 's3://bucket1/',
            })

key = response['QueryExecutionId'] + '.csv'

copy_source = {
    'Bucket': 'bucket1',
    'Key': key
}
s3.meta.client.copy(copy_source, 'bucket2', 'main.csv')

Ошибка: -

Traceback (most recent call last):
  File "/Users/tanmaysinghal/Vizualization/Python Scripts/test.py", line 23, in <module>
    s3.meta.client.copy(copy_source, 'bucket2', 'main.csv')
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/boto3/s3/inject.py", line 379, in copy
    return future.result()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/s3transfer/futures.py", line 106, in result
    return self._coordinator.result()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/s3transfer/futures.py", line 265, in result
    raise self._exception
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/s3transfer/tasks.py", line 255, in _main
    self._submit(transfer_future=transfer_future, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/s3transfer/copies.py", line 110, in _submit
    **head_object_request)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/botocore/client.py", line 661, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (404) when calling the HeadObject operation: Not Found

1 Ответ

0 голосов
/ 03 мая 2019

Существует фундаментальная проблема с вашим кодом, то есть вы пытаетесь скопировать файл Athena S3 output до завершения запроса. Когда вы видите это в консоли, вам требуется несколько секунд, чтобы увидеть, и к этому времени файл готов. Вам нужно подождать, пока Athena завершит ваш запрос, и введите output в S3.

Вот как работает Афина:

  1. Отправить запрос.
  2. Проверьте status вашего запроса.
  3. Если статус running, подождите и перейдите к шагу 2. Elseif SUCCEEDED, перейдите к шагу 4. В противном случае FAILED, затем выполните корректирующее действие.
  4. читать вывод S3 file.

Вот рабочий код.

import boto3
import time
athena = boto3.client('athena')
# s3 = boto3.resource('s3')
# BUCKET_NAME = 'bucket1'
# bucket = s3.Bucket(BUCKET_NAME)

query = 'SELECT *  FROM your-database.your-table  limit 10'
response = athena.start_query_execution(QueryString=query, QueryExecutionContext={
            'Database': 'your-database'
            }, ResultConfiguration={
            'OutputLocation': 's3://your-s3-output-bucket',
            })

execution_id = response['QueryExecutionId']

key = execution_id + ".csv"
state = 'RUNNING';
##waiting for query to complete and then read the result.
while (state in ['RUNNING']):
    response = athena.get_query_execution(QueryExecutionId=execution_id)
    if 'QueryExecution' in response and \
                'Status' in response['QueryExecution'] and \
                'State' in response['QueryExecution']['Status']:
            state = response['QueryExecution']['Status']['State']
            if state == 'FAILED':
                print("FAILED")
            elif state == 'SUCCEEDED':
                s3_path = response['QueryExecution']['ResultConfiguration']['OutputLocation']
                print("S3-Path:" + s3_path)
    time.sleep(1)

# If state is succeeded, meaning query has completed successfully, now, you could read the output file or try copy it to somewhere else.
if state == 'SUCCEEDED':
    copy_source = {
        'Bucket': 'your-s3-output-bucket',
        'Key': key
    }
    s3.meta.client.copy(copy_source, 'bucket2', 'main.csv')

Надеюсь, это поможет вам!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...