Чтение шейп-файла в функциях Azure

#python #azure-functions #azure-blob-storage #shapefile

#python #azure-функции #azure-blob-хранилище #шейп-файл

Вопрос:

Я использую функцию Azure, написанную на Python, для чтения шейп-файла, который поступает из большого двоичного объекта. Конфигурация является

 {
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "inputShp",
      "type": "blobTrigger",
      "direction": "in",
      "path": "uploads/shapefile/{name}.shp",
      "connection": "StorageConnectionString"
    }
  ]
}
  

и __init__.py скрипт

 import logging
from json import dumps
import shapefile
import azure.functions as func

def main(inputShp: func.InputStream):
    logging.info(f"Python blob trigger function processed blob n"
                  f"Name: {inputShp.name}n"
                  f"Blob Size: {inputShp.length} bytes")

    reader = shapefile.Reader(inputShp.read())
  

Но это выдает ошибку

 Exception: ShapefileException: Shapefile Reader requires a shapefile or file-like object.
  

Я попытался использовать reader = shapefile.Reader(io.BytesIO(inputShp.read())) вместо этого, что выдает ошибку

 error: unpack requires a buffer of 4 bytes
  

Ответ №1:

Вы также можете загружать шейп-файлы из любого объекта, подобного файлу Python, используя аргументы ключевого слова для указания любого из трех файлов. Эта функция очень мощная и позволяет загружать шейп-файлы с URL-адреса, из zip-файла, сериализованного объекта или, в некоторых случаях, из базы данных.

Ниже приведен пример для того же

 >>> myshp = open("shapefiles/blockgroups.shp", "rb")
>>> mydbf = open("shapefiles/blockgroups.dbf", "rb")
>>> r = shapefile.Reader(shp=myshp, dbf=mydbf)
  

Используйте open вместо read.В качестве альтернативы попробуйте приведенный ниже пример

 from __future__ import print_function
import zipfile
import StringIO
import shapefile

zipshape = zipfile.ZipFile(open(r'C:GISTempRoadsShapefileFolder.zip', 'rb'))
print(zipshape.namelist())
dbfname, _, shpname, _, shxname = zipshape.namelist()
r = shapefile.Reader(shp=StringIO.StringIO(zipshape.read(shpname)),
                     shx=StringIO.StringIO(zipshape.read(shxname)),
                     dbf=StringIO.StringIO(zipshape.read(dbfname)))

print(r.bbox)
print(r.numRecords)
  

Это тоже должно сработать. Надеюсь, это поможет.

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

1. Файлы передаются как func.InputStream , поэтому они не находятся ни в каком «физическом» расположении. Ваше решение работает, только если вы открываете файл из локального расположения

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

3. Это противоречит цели использования blob из Azure и функций Azure всех вместе, о чем не идет речь. В настоящее время я делаю это на сервере, но я хочу перейти на функции Azure, чтобы сделать это лучше

Ответ №2:

Похоже, что чтение шейп-файлов из потока — это то, что позволяет выполнять MemoryFile (или, возможно, MemoryZipFile) Fiona.

Не тестировался, но стоит проверить.

https://fiona.readthedocs.io/en/latest/fiona.html#fiona.io.MemoryFile

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

1. хм, тогда я проведу несколько тестов fiona

2. не работает, по-видимому, нет способа загрузить более одного файла с помощью MemoryFile , а для шейп-файла нам нужно прочитать shp , dbf и shx файлы: github.com/Toblerity/Fiona/issues/613

3. Ах. Что вы могли бы сделать, так это создать zip-файл с шейп-файлом и всеми файлами sidecar), прежде чем помещать его в большой двоичный объект в первую очередь? А затем используйте MEMORYZIP-файл

4. Но я предполагаю, что шейп-файлы — не лучший формат для выполнения подобных действий. Есть ли у вас возможность использовать другой формат, например geopackage?