#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/6133. Ах. Что вы могли бы сделать, так это создать zip-файл с шейп-файлом и всеми файлами sidecar), прежде чем помещать его в большой двоичный объект в первую очередь? А затем используйте MEMORYZIP-файл
4. Но я предполагаю, что шейп-файлы — не лучший формат для выполнения подобных действий. Есть ли у вас возможность использовать другой формат, например geopackage?