#python #amazon-web-services #aws-lambda #python-requests #multipart
#python #amazon-web-services #aws-lambda #python-запросы #multipart
Вопрос:
Привет, пытаясь извлечь файл из S3 и передать его в конечную точку multipart post в другой службе, код выглядит примерно так
def execute(event, context):
if "emailId" in event:
props = {
"fieldOne": "someValue",
"fieldTwo": "someOtherValue",
"contentType": "eml"
}
props = json.dumps(props)
file = download_s3_file_to_tmp(event["emailId"])
multipart_request(props, file, event["emailId"])
def download_s3_file_to_tmp(message_id):
s3_key = "".join([_email_bucket_folder_name, "/", str(message_id), ".eml"])
s3_client = boto3.client("s3", _region)
s3_client.download_file(_my_bucket, s3_key, "/tmp/" str(message_id) ".eml")
downloaded_eml_file = open("/tmp/" str(message_id) ".eml", 'rb')
return downloaded_eml_file
def multipart_request(props, file_content, message_id):
my_id = *****
secret = *****
url = f"{_url}/...."
payload = {"props": props}
files = [{"fileContent", file_content}]
tmp_file_path = "/tmp/" message_id ".eml"
if os.path.exists(tmp_file_path):
os.remove(tmp_file_path)
print("Removed the file %s" % tmp_file_path)
else:
print("File %s does not exist." % tmp_file_path)
LOGGER.info(f"payload: {payload}")
resp = requests.post(url,data=payload,files=files,auth=requests.auth.HTTPBasicAuth(my_id, secret))
LOGGER.info(f"Request Headers: {resp.request.headers}")
return resp.status_code, resp.text, filenote_id
Проблема в том (при тестировании с одним и тем же файлом из корзины S3, поэтому там не должно быть несоответствий), что периодически я получаю сообщение об ошибке
"errorMessage": "expected string or bytes-like object",
"errorType": "TypeError",
при вызове requests.post. Иногда это нормально, я получаю 200, но много времени я получаю вышеуказанную ошибку.
вот трассировка стека, касающаяся модуля запросов
{
"errorMessage": "expected string or bytes-like object",
"errorType": "TypeError",
"stackTrace": [
" File "/var/task/my_lambda.py", line 42, in executen multipart_request(props, file, event["emailId"])n",
" File "/var/task/mime_retrieval_parser.py", line 75, in multipart_requestn resp = requests.post(url,data=payload,files=files,auth=requests.auth.HTTPBasicAuth(edm_id, edm_secret))n",
" File "/opt/python/requests/api.py", line 119, in postn return request('post', url, data=data, json=json, **kwargs)n",
" File "/opt/python/requests/api.py", line 61, in requestn return session.request(method=method, url=url, **kwargs)n",
" File "/opt/python/requests/sessions.py", line 516, in requestn prep = self.prepare_request(req)n",
" File "/opt/python/requests/sessions.py", line 449, in prepare_requestn p.prepare(n",
" File "/opt/python/requests/models.py", line 317, in preparen self.prepare_body(data, files, json)n",
" File "/opt/python/requests/models.py", line 505, in prepare_bodyn (body, content_type) = self._encode_files(files, data)n",
" File "/opt/python/requests/models.py", line 166, in _encode_filesn rf.make_multipart(content_type=ft)n",
" File "/opt/python/urllib3/fields.py", line 267, in make_multipartn self._render_parts(n",
" File "/opt/python/urllib3/fields.py", line 225, in _render_partsn parts.append(self._render_part(name, value))n",
" File "/opt/python/urllib3/fields.py", line 205, in _render_partn return self.header_formatter(name, value)n",
" File "/opt/python/urllib3/fields.py", line 116, in format_header_param_html5n value = _replace_multiple(value, _HTML5_REPLACEMENTS)n",
" File "/opt/python/urllib3/fields.py", line 89, in _replace_multiplen result = pattern.sub(replacer, value)n"
]
}
Комментарии:
1. Пожалуйста, укажите всю трассировку стека в вашем вопросе. В противном случае нам придется визуально сканировать ваш код, чтобы идентифицировать строку. Конечно, мы можем искать »
requests.post
вызов». Но вы не должны ожидать, что люди будут тратить на это время, если вы хотите, чтобы они вам помогли.2. Я не включил, потому что я обновил имена своих функций для вопроса. Исходные связаны с моей работой, поэтому я не хочу публиковать их на SO. Я вскоре отредактирую трассировку с новыми составными именами и обновлю вопрос, но буквально всего в 2 строках говорится, что это происходит в запросе post.
Ответ №1:
Решаемая проблема с помощью приведенного ниже подхода
def execute(event, context):
if "emailId" in event:
props = {
"fieldOne": "someValue",
"fieldTwo": "someOtherValue",
"contentType": "eml"
}
tmp_file_path = "/tmp/" message_id ".eml"
props = json.dumps(props)
file = download_s3_file_to_tmp(event["emailId"])
multipart_request(props, file, tmp_file_path)
def download_s3_file_to_tmp(message_id, tmp_file_path):
s3_key = "".join([_bucket_folder_name, "/", str(message_id), ".eml"])
s3_client.download_file(
_my_bucket, s3_key, "/tmp/" str(message_id) ".eml"
)
return open(tmp_file_path).read()
def multipart_request(props, opened_eml_file, tmp_file_path):
my_id = *****
secret = *****
url = f"{_url}/...."
payload = {"props": props}
files = {"fileContent": ("whatEverYouWantToNameFile.eml", opened_eml_file)}
if os.path.exists(tmp_file_path):
os.remove(tmp_file_path)
print("Removed the file %s" % tmp_file_path)
else:
print("File %s does not exist." % tmp_file_path)
resp = requests.post(url,data=payload,files=files,auth=requests.auth.HTTPBasicAuth(my_id, secret))
return resp.status_code, resp.text, filenote_id