背景介绍Postgresql+PostGIS是空间数据存储、处理和分析的常用方案。我相信大多数GISer都和我一样。安装好PostGIS后的第一件事就是研究如何将EsriShapefiles导入数据库。常用的方法是通过PostGIS提供的数据导入工具导入数据,或者通过shp2psql命令行工具导入。最近在研究Python空间数据处理,想通过Python脚本将shp文件批量导入库。找到了下面两篇文章:https://zhuanlan.zhihu.com/p/41249261https://blog.csdn.net/jin80506/article/details/91386307尝试运行代码,发现有如下问题导入错误,中文乱码,无法导入MultiPolygon。于是修改了基于两者的代码来解决这些问题。Step1.安装依赖包所需的python包主要有:sqlalchemy、geoalchemy2、geopandas、psycopg2。其中一些包依赖于其他包,安装起来很麻烦。建议您使用anaconda来安装它们。2.准备工作首先创建一个测试数据库gis_test。然后加载PostGIS扩展:CREATEEXTENSIONpostgis;当然也可以使用python连接PostgreSQL创建数据库,加载PostGIS扩展,这里不再赘述。3、代码本文代码删除了上述参考文章中“解析shp的几何代码并获取几何类型”部分,直接将空间数据指定为GEOMETRY类型。"""shp2pgsql.pyimportShapefiletoPostgreSQL.author:mangoversion:0.1.0CompatiblewithPythonversions3.x"""importgeopandasasgdfromsqlalchemyimportcreate_enginefromgeoalchemy2importGeometry,WKTElementimportosdefshp2pgsql(文件,单引擎):""shp文件存储"""file_name=os.path.split(file)[1]print('Writing:'+file)tbl_name=file_name.split('.')[0]#表名map_data=gpd.GeoDataFrame.from_file(file)spatial_ref=map_data.crs.srs.split(':')[-1]#读取shp的空间参考map_data['geometry']=map_data['geometry'].apply(lambdax:WKTElement(x.wkt,spatial_ref))#geopandas的to_sql()方法继承自pandas,将GeoDataFrame中的数据写入数据库map_data.to_sql(name=tbl_name,con=engine,if_exists='replace',#如果表如果存在,将原表替换为chunksize=1000,#设置一次存储大小,防止数据过多卡住#指定geometry的类型,这里直接指定geometry_type='GEOMETRY'防止MultiPolygon写不出来dtype={'geometry':Geometry(geometry_type='GEOMETRY',srid=spatial_ref)},method='multi')returnNonedefshp2pgsql_batch(dir_name,username,password,host,port,dbname):"""Createbatchtask"""os.chdir(dir_name)#将当前工作目录更改为指定目录pathengine=create_engine(username,password,host,port,dbname)file_list=os.listdir(dir_name)forfileinfile_list:iffile.split('.')[-1]=='shp':file=os.path.abspath(file)shp2pgsql(file,engine)returnNone#执行任务计划if__name__=='__main__':file_path=r'D:\Data\mango'username='postgres'password='123ewq'host='127.0.0.1'port='5432'dbname='gis_test'shp2pgsql_batch(file_path,username,password,host,port,dbname)使用改进后的代码测试各种点、线、面数据,都可以成功写入,并且没有中文乱码问题,大功告成!
