Извлечение нескольких сжатых файлов JSON в памяти и сохранение их в хранилище больших двоичных объектов Azure с помощью Python

#python #azure #azure-storage #azure-blob-storage

Вопрос:

У меня есть функция, которая взаимодействует с API SOAP, получает двоичные файлы и в конечном итоге извлекает небольшое количество файлов JSON, которые я хочу сохранить в контейнере хранилища больших двоичных объектов Azure с помощью Python.

Официальная документация и примеры Microsoft полезны для сохранения одного файла, но когда я пытаюсь сделать то же самое для нескольких файлов, я получаю код ошибки:

Ошибка типа: Данные большого двоичного объекта должны иметь тип байт.

Ниже приведена ячейка кода и код ошибки.

 # Extract Pre Survey JSON responses from binaries and send to Azure Blob storage:

import os
import io, zipfile
from io import BytesIO
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, __version__
from functools import reduce

blob = BlobClient.from_connection_string(conn_str="connection string", container_name="container name", blob_name=name)

local_path = "./temp"

def temp_extract():
  for i in binaries: ---> N.B from previous cell.  
    with zipfile.ZipFile(io.BytesIO(i)) as zfile: 
      for name in zfile.namelist():
        if name.endswith('.json'):
          zfile.extract(name, local_path)

def  upload_blobs():
  upload_file_path = os.path.join(local_path, name)
  onlyfiles = reduce(lambda x,y : x y, [map(lambda x: root   "/"   x, files) for root, dirs, files in os.walk(local_path)])
  onlyfiles = [file for file in onlyfiles if file.endswith('.json')]
  for file in onlyfiles:
      print(os.path.getsize(file))
      with open(file, 'r') as f:
        blob.upload_blob(data = f, overwrite=True)

if __name__ == '__main__':
    temp_extract()
    upload_blobs()
 

Я получаю следующий код ошибки:

 TypeError                                 Traceback (most recent call last)
<ipython-input-273-fb49f396fab5> in <module>
     26 if __name__ == '__main__':
     27     temp_extract()
---> 28     upload_blobs()
     29 

<ipython-input-273-fb49f396fab5> in upload_blobs()
     22       print(os.path.getsize(file))
     23       with open(file, 'r') as f:
---> 24         blob.upload_blob(data = f, overwrite=True)
     25 
     26 if __name__ == '__main__':

~/Library/Python/3.7/lib/python/site-packages/azure/core/tracing/decorator.py in wrapper_use_tracer(*args, **kwargs)
     81             span_impl_type = settings.tracing_implementation()
     82             if span_impl_type is None:
---> 83                 return func(*args, **kwargs)
     84 
     85             # Merge span is parameter is set, but only if no explicit parent are passed

~/Library/Python/3.7/lib/python/site-packages/azure/storage/blob/_blob_client.py in upload_blob(self, data, blob_type, length, metadata, **kwargs)
    683             **kwargs)
    684         if blob_type == BlobType.BlockBlob:
--> 685             return upload_block_blob(**options)
    686         if blob_type == BlobType.PageBlob:
    687             return upload_page_blob(**options)

~/Library/Python/3.7/lib/python/site-packages/azure/storage/blob/_upload_helpers.py in upload_block_blob(client, data, stream, length, overwrite, headers, validate_content, max_concurrency, blob_settings, encryption_options, **kwargs)
     86                 data = data.read(length)
     87                 if not isinstance(data, six.binary_type):
---> 88                     raise TypeError('Blob data should be of type bytes.')
     89             except AttributeError:
     90                 pass

**TypeError: Blob data should be of type bytes.**
 

Ответ №1:

Причина, по которой вы получаете эту ошибку, заключается в том, что вы передаете файловый объект в качестве данных методу upload_blob, в то время как метод ожидает содержимое.

Что бы вы сделали, это прочитали содержимое файла, а затем передали содержимое файла методу upload_blob.

Что-то вроде:

 with open(file, 'r') as f:
    file_content = f.read()  
    blob.upload_blob(data = file_content, overwrite=True)
 

Комментарии:

1. Спасибо вам за помощь. Это избавляет от кода ошибки и фактически загружает что — то в контейнер, но по какой-то причине он сохраняет только один из трех файлов и использует неправильный формат файла и имя файла-На предыдущем шаге (извлечение данных из API SOAP) я получаю три файла json и три файла txt, которые описывают вышеупомянутые файлы json. Я получаю последний файл json в большом двоичном объекте, но названный в честь одного из файлов txt, который был отфильтрован с помощью «onlyfiles = [файл для файла в onlyfiles, если файл.endswith(‘.json’)]»

2. Может быть, это потому, что вы задаете фиксированное имя большого двоичного объекта: blob = BlobClient.from_connection_string(conn_str="connection string", container_name="container name", blob_name=name) ? Можете ли вы попробовать создать экземпляр BlobClient непосредственно перед вызовом метода upload_blob и посмотреть, решит ли это вашу проблему?

3. Идеально! Я рад это слышать.