mdb转gdb实现过程介绍(2)三种方式实现GDB数据库的读、写,并将实现方式与ArcGIS环境共存配置

发布于:2024-07-03 ⋅ 阅读:(13) ⋅ 点赞:(0)

一、内容提示


        通过解析mdb地理数据库,获取了图层之间的组织结构、空间参考、表字段属性等信息。

        下一步,就是将数据输出到GDB中。

        下面详细介绍python3.9版本,读写GDB数据的方法:

        (1)使用ArcPy创建GDB、读写GDB;

        (2)使用osgeo创建、读写GDB;

        (3)使用fiona、geopandas创建、读写GDB;

        (4)将osgeo或geopandas模块添加到自定义模块,实现其与ArcGIS环境的共存

图片

        MDB转出为GDB,涉及的内容比较多,尤其是需要开源实现。每一篇文章的内容篇幅都很长,希望对大家有帮助。

        (1)mdb(个人地理数据库)转shape file其实并不简单

        (2)mdb转gdb实现过程介绍(1)mdb地理数据库结构解析和gdb库的创建


 

二、FileGDB驱动

        GDB是Esri开发的一种地理数据库格式,它旨在存储和管理地理空间数据。GDB可以包含矢量数据、栅格数据、拓扑数据、地图符号化信息以及数据集之间的关联关系等。

        GDB作为Esri的一种地理数据库格式,并非完全开源,它提供了开放式的文件规范和API,在一定程度上允许与其他软件集成和交互。

        在以往(python<3.9),都是通过配置FileGDB驱动,实现对GDB数据的读写。

        在使用习惯上,一般有两种办法:

        (1)通过安装GDAL的方式添加FileGDB驱动

        一般是通过osgeo中的ogr实现GDB文件的读写,需要拷贝FileGDBAPI.dll至python安装目录下的“\Lib\site-packages\osgeo”;

        FileGDBAPI.dll下载地址:

            https://github.com/Esri/file-geodatabase-api

        GDAL的whl文件下载地址:

            https://github.com/cgohlke/geospatial-wheels/releases

        GDAL 3.x 版本,还需要把gdalplugins\disabled中的ogr_FileGDB.dll移动到gdalplugins目录;

GDAL 2.x版本,修改osgeo/__init__.py文件:注释15行,取消注释17行,如下:

# __init__ for osgeo package.# unofficial Windows binaries: set GDAL environment variables if necessaryimport ostry:    _here = os.path.dirname(__file__)    if _here not in os.environ['PATH']:        os.environ['PATH'] = _here + ';' + os.environ['PATH']    if 'GDAL_DATA' not in os.environ:        os.environ['GDAL_DATA'] = os.path.join(_here, 'data', 'gdal')    if 'PROJ_LIB' not in os.environ:        os.environ['PROJ_LIB'] = os.path.join(_here, 'data', 'proj')    if 'GDAL_DRIVER_PATH' not in os.environ:        #pass        # uncomment the next line to enable plugins        os.environ['GDAL_DRIVER_PATH'] = os.path.join(_here, 'gdalplugins')except Exception:    passdel os

        (2)使用'fiona'引擎实现,一般是通过geopandas完成GDB文件的读写

        为了方便介绍,假设利用conda新建一个geopandas的虚拟环境,复制FileGDBAPI.dll文件,粘贴到利用conda新建的虚拟环境根目录下的Library\bin里。然后将ogr_FileGDB.dll这个文件放置于前面FileGDBAPI.dll同级目录下的gdalplugins目录中即可。

三、OpenFileGDB驱动

        前文对python的版本进行了高亮,这个版本的分水岭是3.9,现在对这个版本分界的原因做一个简单的说明。

        在python3.9版本,用前文的方法配置FileGDB驱动已经行不通了,而小编也尝试了多种方法,并没有成功。有成功配置FileGDB驱动的小伙伴,望指导。

        于是,我将方向转为配置OpenFileGDB驱动。

        关于FileGDB驱动与OpenFileGDB驱动的详细介绍,可以通过GDAL社区文档获的相关信息。文档地址为:https://gdal.org/

        (1)FileGDB驱动

  • FileGDB驱动是用于ArcGIS File Geodatabase(FileGDB)格式的驱动程序,允许在GDAL/OGR库中读取和写入FileGDB数据。

  • 这个驱动是专门为ArcGIS FileGDB格式设计的,是Esri提供的官方支持。

        (2) OpenFileGDB驱动

  • OpenFileGDB驱动也是用于ArcGIS File Geodatabase(FileGDB)格式的驱动程序,但是它是GDAL/OGR库的一部分,提供了对FileGDB格式的开源支持。

  • OpenFileGDB驱动允许在GDAL/OGR库中使用FileGDB数据,无需依赖ArcGIS软件。

        在python3.9版本之前,安装的fiona包含了'OpenFileGDB'驱动,OpenFileGDB就是gdal中默认自带的针对gdb文件的驱动,但其对应的值为'r',说明它只能针对gdb文件进行读取。

图片

        ArcGIS Pro 3.1版本,使用的Python版本是3.9.16。克隆的python环境,在安装了fiona后,惊奇的发现,其对OpenFileGDB的支持,已经是“raw”。

图片

        但是,现实总是残酷的。要想通过fiona实现对gdb数据的写入,需要gdal的版本在3.6.0以上,而当前gdal的版本为3.4.0。报错信息如下:

图片

        因此,现在的目标转为升级gdal版本到3.6.0以上。这时候,需要考虑的因素为:

  • 若脚本需要封装为python工具箱,直接使用Pro的python环境或基于Pro克隆的python环境,是不让升级gdal版本的;(得另想办法)
  • 若脚本后续不会使用到arcgis或arcpy模块,则直接安装3.6.0及以上的gdal版本即可;

四、3种GDB的创建、读写方法

4.1  ArcPy 创建、读写GDB数据

        使用ArcPy可以轻松地创建、读取和写入Geodatabase(GDB)数据。下面分别介绍如何创建GDB数据和如何读取/写入GDB数据,并附上示意代码。

        (1)创建GDB数据

        要创建GDB数据,可以使用CreateFileGDB_management函数。

import arcpy# 设置工作空间arcpy.env.workspace = r"C:\path\to\your\workspace"# 定义GDB名称和保存路径gdb_name = "MyGDB.gdb"gdb_path = arcpy.env.workspace# 创建GDBarcpy.CreateFileGDB_management(gdb_path, gdb_name)

        (2)读取GDB数据

        要读取GDB数据,可以使用ListFeatureClasses和ListTables函数来列出GDB中的要素类和表。

import arcpy# 设置工作空间arcpy.env.workspace = r"C:\path\to\your\workspace\MyGDB.gdb"# 获取要素类列表feature_classes = arcpy.ListFeatureClasses()# 获取表列表tables = arcpy.ListTables()# 打印要素类和表名print("Feature Classes:")for fc in feature_classes:    print(fc)print("\nTables:")for table in tables:    print(table)

        (3)写入GDB数据

        要写入GDB数据,可以使用相应的InsertCursor来插入新的要素或记录到要素类或表中。

import arcpy# 设置工作空间arcpy.env.workspace = r"C:\path\to\your\workspace\MyGDB.gdb"# 要素类路径fc_path = "MyFeatureClass"# 字段列表fields = ["Field1", "Field2"]# 创建InsertCursorwith arcpy.da.InsertCursor(fc_path, fields) as cursor:    # 插入新要素    cursor.insertRow(("Value1", "Value2"))

4.2  osgeo 创建、读写GDB数据

     安装gdal,使用osgeo的ogr实现GDB的创建、读写。

    步骤:

  • 在python3.9版本中安装gdal3.8.4;
  •  使用org创建、读写GDB数据;

        (1)安装GDAL3.8.4

        为了便于后续osgeo及其依赖迁移到自定义模块中,使用conda新建一个虚机环境。

        01 在python3.9中安装gdal

#在conda默认envs目录下创建虚拟环境osgeo-write-gdb-testconda create -n osgeo-write-gdb-test python=3.9 -c https://mirrors.sjtug.sjtu.edu.cn/anaconda/pkgs/main -y#conda在指定目录下创建虚拟环境osgeo-write-gdb-testconda create --prefix C:\ProgramData\Miniconda3\envs\osgeo-write-gdb-test python=3.9.16

        下载GDAL-3.8.4-cp39-cp39-win_amd64.whl,我们知道,https://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml网站已经打不开了,而GDAL在CSDN上下载,又需要会员或积分,需要GDAL的,可到https://github.com/cgohlke/geospatial-wheels/releases中下载。

        安装gdal:GDAL-3.8.4-cp39-cp39-win_amd64.whl

pip install GDAL-3.8.4-cp39-cp39-win_amd64.whl

图片

        (2) osgeo创建、读写gdb

        在解释器osgeo-write-gdb-test下,新建GDB和图层。

from osgeo import ogr, osr, gdal# 设置新的GDB文件路径gdb_file_path = './new_demo.gdb'# 创建数据驱动driver = ogr.GetDriverByName("OpenFileGDB")data_source = driver.CreateDataSource(gdb_file_path)if data_source is not None:    print("Successfully created GDB:", gdb_file_path)else:    print("Failed to create GDB:", gdb_file_path)# 获取并打印 GDAL 的版本信息print("GDAL Version:", gdal.__version__)# 创建数据驱动driver = ogr.GetDriverByName("OpenFileGDB")data_source = driver.Open(gdb_file_path, 1)  # 1 表示以写入模式打开数据源,如果数据源不存在则创建新的# 创建坐标系和图层if data_source is not None:    srs = osr.SpatialReference()    srs.ImportFromEPSG(4490)  # 你所需的 EPSG 编码    outLayer = data_source.CreateLayer("ds", srs=srs, geom_type=ogr.wkbPolygon)  # 创建图层    if outLayer is None:        print("Layer creation failed!")else:    print("OpenFileGDB driver is not available.")

        上述代码,在当前目录创建一个名为“new_demo”的gdb,并在该gdb中新建一个图层“ds”,执行结果如下:

图片

4.3  fiona、geopandas 创建、读写GDB数据

        安装geopandas,分别使用geopandas和fiona实现GDB的创建、读写。

        步骤:

  • 在python3.9版本中安装geopandas;
  • 创建、读写GDB数据;

        (1) 安装geopandas

        为了便于后续geopandas及其依赖迁移到自定义模块中,使用conda新建一个虚机环境。

        01 在python3.9中安装geopandas

#在conda默认envs目录下创建虚拟环境geopandas-write-gdb-testconda create -n geopandas-write-gdb-test python=3.9 -c https://mirrors.sjtug.sjtu.edu.cn/anaconda/pkgs/main -y#conda在指定目录下创建虚拟环境geopandas-write-gdb-testconda create --prefix C:\ProgramData\Miniconda3\envs\geopandas-write-gdb-test python=3.9.16#安装geopandasconda install geopandas -c https://mirrors.sjtug.sjtu.edu.cn/anaconda/cloud/conda-forge -y

        (2) 创建、读写GDB数据

        01 使用geopandas创建、读写gdb

        在解释器geopandas-write-gdb-test下,新建GDB和图层。

import geopandas as gpdfrom shapely.geometry import Point, LineString, Polygondemo_point_layer = gpd.GeoDataFrame(    {        '数据字段测试': ['点要素测试数据字段测试'],        'geometry': [Point(0, 0)]    },    crs='EPSG:4326')demo_linestring_layer = gpd.GeoDataFrame(    {        '数据字段测试': ['线要素测试数据字段测试'],        'geometry': [LineString([(0, 0), (1, 1)])]    },    crs='EPSG:4326')demo_polygon_layer = gpd.GeoDataFrame(    {        '数据字段测试': ['面要素测试数据字段测试'],        'geometry': [Polygon([(0, 0), (1, 1), (1, 0)])]    },    crs='EPSG:4326')# 写出到示例gdb文件中demo_point_layer.to_file('./demo1.gdb', layer='点图层测试', driver='OpenFileGDB')demo_linestring_layer.to_file('./demo1.gdb', layer='线图层测试', driver='OpenFileGDB')demo_polygon_layer.to_file('./demo1.gdb', layer='面图层测试', driver='OpenFileGDB')

        上述代码,在当前目录创建一个名为“demo1”的gdb,并在该gdb中新建一个图层三个图层,执行结果如下:

图片

        02 使用fiona创建、读写gdb

import fiona# 创建示例数据demo_polygon = {    'type': 'Polygon',    'coordinates': [[(0, 0), (1, 1), (1, 0), (0, 0)]]}# 设置文件路径gdb_file = './demo2.gdb'# 将投影数据文件添加到环境变量中# import os# os.environ["PROJ_LIB"] = "C:/proj"# 创建GDB文件和图层with fiona.open(gdb_file, 'w', driver='OpenFileGDB', crs='EPSG:4326', layer='polygon_layer', schema={'geometry': 'Polygon', 'properties': {}}) as layer:    layer.write({'geometry': demo_polygon, 'properties': {}})# 读取GDB数据with fiona.open(gdb_file, 'r', driver='OpenFileGDB') as layer:    for feature in layer:        print(feature)

        执行上述代码,会报错“fiona.errors.CRSError: The WKT could not be parsed. PROJ: proj_create_from_database: Cannot find proj.db”,如下所示:

图片

        这个错误是fiona缺失投影数据的定义文件(通常是 proj 文件)引起的。可通过将proj文件夹添加到环境变量中解决。

        注意:

  • 通过直接安装geopandas,不能获得proj 文件。需要安装GDAL后,在‘\Lib\site-packages\osgeo\data\proj’处获得,可在代码执行中自动将其添加到环境变量中解决;
  • os.environ["PROJ_LIB"] 添加的proj路径,不能包含中文;
import osos.environ["PROJ_LIB"] = "C:/proj"

图片

        生成的gdb如下:

图片

 

五、osgeo、fiona、geopandas 开源读、写gdb,如何与Arcpy环境共存?

        前面我们通过开源的方式实现了对GDB的创建和读写,但是都是在原生安装GDAL和Geopandas的虚机环境中。

        如果我们需要调用arcpy或arcgis模块,或后期将脚本封装为工具,就需要将实现gdb读、写实现的模块放到自定义模块中,并实现其与ArcGIS环境的共存。

        步骤:

        (1)创建自定义模块,将开源读写gdb的模块置于其中;

        (2)使用ogr创建gdb,并使用arcpy获取图层列表;

        (3)使用fiona创建gdb,并使用arcpy获取图层列表;

        (4)使用geopandas创建gdb,并使用arcpy获取图层列表。

5.1  将开源实现读、写gdb,组织到自定义模块中

        这部分非常重要。我们知道,ArcGIS Pro的python环境是不允许我们添加包的,而我们为了添加包,就需要克隆python环境,再在克隆环境中添加包。但是我们会碰到非常尴尬的两个问题:

        (1)安装的包可能与克隆环境内的包版本冲突,导致无法正常安装或后续莫名其妙的错误;

        (2)当我们基于Pro自定义python工具箱后,那些我们定义的工具,可能在克隆环境中添加了第三方包,这在部署和推广使用时,带来了很大的不便。

        01 将gdal添加到自定义模块

        我们在通过conda创建的虚拟环境osgeo-write-gdb-test中,安装GDAL-3.8.4-cp39-cp39-win_amd64.whl,在site-packages文件夹下,能看到我们已经安装的包或模块。如下图:

图片

        我们将上图中绿框中的三个文件夹,拷贝至我们自定义的文件夹“myosgeo”中,并在myosgeo文件夹下创建__init__.py。如下图:

图片

在__init__.py文件夹中添加如下代码:​​​​​​


import os
import sys

# 获取当前模块所在目录的路径
module_dir = os.path.dirname(__file__)

# 将当前模块所在目录添加到sys.path中
sys.path.insert(0, module_dir)

        02 将geopandas添加到自定义模块

import osimport sys
# 获取当前模块所在目录的路径module_dir = os.path.dirname(__file__)
# 将当前模块所在目录添加到sys.path中sys.path.insert(0, module_dir)

        03 将geopandas添加到自定义模块

        我们在通过conda创建的虚拟环境geopandas-write-gdb-test中,site-packages文件夹下,将geopandas及其依赖的模块拷贝到“myenv"文件夹中,并添加__init__.py,__init__.py内的内容相同。

        拷贝的内容如下:

图片

 

5.2  使用自定义模块中的ogr创建gdb,使用arcpy读取gdb

        测试示例代码如下:

from mygeos.osgeo import ogr, osr, gdalimport arcpy# 设置新的GDB文件路径gdb_file_path = './new_demo_arcpy.gdb'# 创建数据驱动driver = ogr.GetDriverByName("OpenFileGDB")data_source = driver.CreateDataSource(gdb_file_path)if data_source is not None:    print("Successfully created GDB:", gdb_file_path)else:    print("Failed to create GDB:", gdb_file_path)# 获取并打印 GDAL 的版本信息print("GDAL Version:", gdal.__version__)# 创建数据驱动driver = ogr.GetDriverByName("OpenFileGDB")data_source = driver.Open(gdb_file_path, 1)  # 1 表示以写入模式打开数据源,如果数据源不存在则创建新的# 创建坐标系和图层if data_source is not None:    srs = osr.SpatialReference()    srs.ImportFromEPSG(4490)  # 你所需的 EPSG 编码    outLayer = data_source.CreateLayer("使用自定义ogr创建的测试图层", srs=srs, geom_type=ogr.wkbPolygon)  # 创建图层    if outLayer is None:        print("Layer creation failed!")else:    print("OpenFileGDB driver is not available.")data_source = Nonearcpy.env.workspace = gdb_file_pathprint(arcpy.ListFeatureClasses())

        输出如下:

图片

5.3  使用自定义模块中的geopandas创建gdb,使用arcpy读取gdb

        测试示例代码如下:

# -*-coding:utf-8-*-import arcpyfrom myenv import geopandas as gpdfrom myenv.shapely.geometry import Point, LineString, Polygondemo_point_layer = gpd.GeoDataFrame(    {        '数据字段测试': ['点要素测试数据字段测试'],        'geometry': [Point(0, 0)]    },    crs='EPSG:4326')demo_linestring_layer = gpd.GeoDataFrame(    {        '数据字段测试': ['线要素测试数据字段测试'],        'geometry': [LineString([(0, 0), (1, 1)])]    },    crs='EPSG:4326')demo_polygon_layer = gpd.GeoDataFrame(    {        '数据字段测试': ['面要素测试数据字段测试'],        'geometry': [Polygon([(0, 0), (1, 1), (1, 0)])]    },    crs='EPSG:4326')# 写出到示例gdb文件中demo_point_layer.to_file('./demo_geopandas.gdb', layer='gdf点图层自定义模块测试', driver='OpenFileGDB')demo_linestring_layer.to_file('./demo_geopandas.gdb', layer='gdf线图层自定义模块测试', driver='OpenFileGDB')demo_polygon_layer.to_file('./demo_geopandas.gdb', layer='gdf面图层自定义模块测试', driver='OpenFileGDB')data_source = Nonearcpy.env.workspace = './demo_geopandas.gdb'print(arcpy.ListFeatureClasses())

        输出如下:

图片

5.4  使用自定义模块中的fiona创建gdb,使用arcpy读取gdb

        测试示例代码如下:

from myenv import fionaimport arcpy# 创建示例数据demo_polygon = {    'type': 'Polygon',    'coordinates': [[(0, 0), (1, 1), (1, 0), (0, 0)]]}# 设置文件路径gdb_file = './demo_fiona.gdb'import osos.environ["PROJ_LIB"] = "C:/proj"# 创建GDB文件和图层with fiona.open(gdb_file, 'w', driver='OpenFileGDB', crs='EPSG:4326', layer='fiona开源自定义模块测试', schema={'geometry': 'Polygon', 'properties': {}}) as layer:    layer.write({'geometry': demo_polygon, 'properties': {}})# 读取GDB数据with fiona.open(gdb_file, 'r', driver='OpenFileGDB') as layer:    for feature in layer:        print(feature)data_source = Nonearcpy.env.workspace = './demo_fiona.gdb'print(arcpy.ListFeatureClasses())

        输出如下:

图片

图片