#python-3.x #amazon-web-services #amazon-s3 #aws-lambda
#python-3.x #amazon-веб-сервисы #amazon-s3 #aws-lambda
Вопрос:
Я пытаюсь загрузить файл из API для загрузки (потоковой передачи) непосредственно в S3.
Мой код для локальных загрузок (который отлично работает):
import requests
import datetime
import os
headers = {'Authorization': 'apikey THISISHIDDEN'}
baseURL = 'https://api.test.au/busschedule/'
target_path = datetime.datetime.now().strftime('%Y-%m-%d schedule') '.zip'
response = requests.get(baseURL, stream=True, headers=headers)
handle = open(target_path, "wb")
for chunk in response.iter_content(chunk_size=512):
if chunk: # filter out keep-alive new chunks
handle.write(chunk)
handle.close()
Моя попытка загрузить и выполнить потоковую передачу на S3 (которая не сработала):
# import requests
import datetime
import os
import boto3
import botocore.vendored.requests.packages.urllib3 as urllib3
# Get environment variables from serverless.yml
bucket = "bucket"
s3folder = "schedules"
# Set standard script parameters
headers = {'Authorization': 'apikey THISISHIDDEN'}
baseURL = 'https://api.test.au/busschedule/'
def run(event, context):
s3 = boto3.client('s3')
datetimestamp = datetime.datetime.today().strftime('%Y%m%dT%H%M%S')
filename = datetimestamp " bus schedule.zip"
key = s3folder '/' filename # your desired s3 path or filename
http = urllib3.PoolManager()
s3.upload_fileobj(http.request('GET', baseURL,
headers=headers, preload_content=False),
bucket, key)
def main():
run({},{})
if __name__ == "__main__":
exit(main())
Ошибка, которую я получаю от CloudWatch, является:
InsecureRequestWarning: Unverified HTTPS request is being made. Timeout after 300.10s.
РЕДАКТИРОВАТЬ: Время ожидания функции lambda составляет 300 секунд; но этого должно быть более чем достаточно для загрузки файла (6 мб). Локальная загрузка выполняется в течение примерно 10 секунд. У кого-нибудь есть лучший подход к этому?
Комментарии:
1. Эта ошибка означает, что это необработанное исключение было вызвано во время инициализации (при импорте вашего кода). Вероятно, какой-то код пытается получить
os.environ['URL']
. Есть вероятность, что здесь чего-то не хватает в коде? Кстати, этот код неверно отформатирован, у вас неверный строковый литерал2. Приношу свои извинения, пытаясь очистить код для Stack Overflow, я загрузил неправильную проблему. Я использую serverless для развертывания кода в AWS Lambda и неправильно назвал переменную среды (URL).
3. Каков объем памяти? Использование малого объема памяти также будет означать низкую пропускную способность сети
4. 512 мб памяти, выделенной для очень маленького (менее 10 мб) файла
5. Я предлагаю сначала выполнить запрос GET, затем загрузку S3 и добавить отпечатки, чтобы увидеть, где происходит тайм-аут. Вы также можете попробовать выбрать файл меньшего размера, чтобы посмотреть, связано ли это как-то.
Ответ №1:
Устранена эта проблема с помощью библиотеки ‘smart_open’:
response = requests.get(baseURL, stream=True, headers=headers)
s3url = 's3://' bucket '/' key
with smart_open(s3url, 'wb') as fout:
fout.write(response.content)
Мне нужно решить еще одну проблему (разрешения Lambda), но это будет отдельный вопрос. Запуск этого локального приложения удался на славу.
Ответ №2:
Другой способ загрузки файла (даже больше 6 МБ) с использованием AWS lambda:
Шаг 1. Создайте предварительно подписанный URL-адрес на основе запроса get или put, верните этот URL-адрес в качестве ответа. Шаг 2: Используйте этот URL-адрес в своем классе программы загрузки файлов в пользовательском интерфейсе.
Плюсы
- Код масштабируется с точки зрения размера файла, поскольку lambda имеет ограничение в 6 МБ, эта логика работает с меньшими и большими данными.
- Предварительно подписанный URL-адрес является безопасным способом, мы можем указать срок для URL-адреса, по истечении которого срок действия URL-адреса истекает.
Минусы
- Это двухэтапный процесс, поэтому для загрузки одного файла необходимо использовать 2 API.
Пожалуйста, не стесняйтесь оставлять отзывы об этом подходе.