Отрицательный поиск в режиме записи

#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