#python #amazon-s3 #gzip #file-handling #oserror
Вопрос:
Я скачал сжатый файл из S3 и попытался распаковать его:
with zipfile.ZipFile('/tmp/DataPump_10000838.zip', 'r') as zip_ref: testList = [] for i in zip_ref.namelist(): if (i.startswith("__MACOSX/") == False): val = '/tmp/' i testList.append(val)
Теперь в моей папке есть несколько распакованных файлов /tmp
. Я хочу открыть эти файлы, gzip и переместить их в корзину S3. Пути к распакованным файлам присутствуют в testList
s3_filename = 'sample' s3_resource = boto3.resource('s3') bucket = s3_resource.Bucket('testunzipping') for i in testList: with contextlib.ExitStack() as stack: source_file = stack.enter_context(open(i , mode="rb")) destination_file = io.BytesIO() destination_file_gz = stack.enter_context(gzip.GzipFile(fileobj=destination_file, mode='wb')) while True: chunk = source_file.read(1024) if not chunk: break destination_file_gz.write(chunk) destination_file_gz.seek(0) bucket.upload_fileobj(destination_file_gz, fileName)
Я пытаюсь это сделать, но получаю ошибку:
Response { "errorMessage": "Negative seek in write mode", "errorType": "OSError", "requestId": "", "stackTrace": [ " File "/var/lang/lib/python3.9/importlib/__init__.py", line 127, in import_modulen return _bootstrap._gcd_import(name[level:], package, level)n", " File "lt;frozen importlib._bootstrapgt;", line 1030, in _gcd_importn", " File "lt;frozen importlib._bootstrapgt;", line 1007, in _find_and_loadn", " File "lt;frozen importlib._bootstrapgt;", line 986, in _find_and_load_unlockedn", " File "lt;frozen importlib._bootstrapgt;", line 680, in _load_unlockedn", " File "lt;frozen importlib._bootstrap_externalgt;", line 850, in exec_modulen", " File "lt;frozen importlib._bootstrapgt;", line 228, in _call_with_frames_removedn", " File "/var/task/lambda_function.py", line 51, in lt;modulegt;n destination_file_gz.seek(0)n", " File "/var/lang/lib/python3.9/gzip.py", line 384, in seekn raise OSError('Negative seek in write mode')n" ] }
Как я могу это исправить?
Ответ №1:
Оболочка gzip Python не поддерживает поиск. Хотя, скорее всего, это не имеет значения, так как вы хотите загрузить байты gzip’d, а не распакованные байты, которые будут получены в результате поиска в представлении gzip. Кроме того, вам нужен close
файл gzip, так как он не знает, что вы закончили запись, и может содержать последний буфер для очистки:
# Ensure the gzip wrapper is done writing its data destination_file_gz.close() # Seek to the start of the raw data, not the gzip'd version destination_file.seek(0) # And upload that raw data bucket.upload_fileobj(destination_file, fileName)
Комментарии:
1. Тогда я бы получил
"I/O operation on closed file.",
ошибку 🙁2. @x89 Ах, да, вы не закрываете файл gz перед его использованием, см. Мою правку.
3. Я вижу, что файлы теперь созданы в S3. Однако тип файла не определен (-). Кроме того, когда я загружаю файл и открываю его, это просто странные символы. Как я узнаю, успешно ли он разархивирован?
4. Если вам нужно задать тип контента, добавьте
ContentType='application/gzip'
его в свой вызов для загрузки. Вы должны иметь возможность открыть файл с помощью программы чтения gzip. Я бы протестировал его с любым компонентом, который вы хотите прочитать в этих файлах.5. Ты имел в виду вот так
bucket.upload_fileobj(destination_file, fileName, ContentType='application/gzip')
Это бросаетbucket_upload_fileobj() got an unexpected keyword argument 'ContentType