ส่งออก shapefile ไปยัง PostGIS ผ่านสคริปต์ Python จาก QGIS

Sep 28 2020

ฉันโพสต์คำถามนี้ใน StackOverFlow ซึ่งแนะนำให้โพสต์ไว้ที่นี่แทน

ฉันต้องการส่งออก shapefile ไปยัง PostGIS ผ่านสคริปต์ Python จาก QGIS ฉันใช้ QGIS 3.10, PostgreSQL 10 และ PostGIS 2.5 บน Windows 10 ฉันลองไปใช้qgis:importintopostgis:

import processing
processing.run("qgis:importintopostgis",{
                'INPUT': 'unioncrs',
                'DATABASE': "HistoPG",
                'SCHEMA': "public",
                'TABLENAME': "testunion",
                'PRIMARY_KEY': "Nummer"
                })

ที่สร้างข้อความแสดงข้อผิดพลาด:

“ .... มีข้อผิดพลาดในการเรียกใช้อัลกอริทึม”

ที่น่าสนใจคือมันทำงานร่วมกับ DB Manager ซึ่งดูเหมือนว่าจะเป็น GUI ของqgis:importintopostgis.

ความแตกต่างที่ฉันเห็นคือ Source และ SRID เป้าหมาย ฉันไม่รู้วิธีป้อนพารามิเตอร์เหล่านี้ใน qgis: importintopostgis ฉันไม่แน่ใจว่าฉันไม่จำเป็นต้องป้อนชื่อผู้ใช้และรหัสผ่านสำหรับฐานข้อมูลหรือไม่ แต่ฉันไม่เห็นว่าจะป้อนพารามิเตอร์เหล่านี้ในที่qgis:importintopostgisใด

ฉันยังลอง `gdal: importvectorintopostgisdatabaseavailableconnections:

processing.run("gdal:importvectorintopostgisdatabaseavailableconnections",{
                'DATABASE': "HistoPG",
                'INPUT': 'C:/QGIS/Vers1/Results/unioncrs.shp',
                'GTYPE': 0,
                'SCHEMA': "public",
                'TABLE': "testunion"
                })

ที่ทำงานโดยไม่มีข้อความแสดงข้อผิดพลาด แต่ยังไม่นำเข้าตารางไปยัง PostGIS ผมทำอะไรผิดหรือเปล่า? มีวิธีการที่ใช้ได้กับ Python จาก QGIS หรือไม่?

สวัสดี @Jakob. ที่ได้ผล ขอขอบคุณ.

สวัสดี @ เดิร์กบี: ฉันวิ่ง:

PARAMETERS = {'DATABASE':'HistoPG','INPUT':'C:\\QGIS\\Vers1\\Results\\unioncrs.shp', 
'SHAPE_ENCODING':'utf-8','GTYPE':0,'A_SRS':QgsCoordinateReferenceSystem('EPSG:31467'),'T_SRS':None,'S_SRS':None,
    'SCHEMA':'public','TABLE':'testunion','PK':'Nummer','PRIMARY_KEY':'','GEOCOLUMN':'geom','DIM':0,'SIMPLIFY':'',
   'SEGMENTIZE':'','SPAT':None,'CLIP':False,'WHERE':'','GT':'','OVERWRITE':True,'APPEND':False,
    'ADDFIELDS':False,'LAUNDER':False,'INDEX':False,'SKIPFAILURES':False,'PROMOTETOMULTI':True,
    'PRECISION':True,'OPTIONS':''}

processing.run("gdal:importvectorintopostgisdatabaseavailableconnections", PARAMETERS)

จากนั้นฉันได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้:

Traceback (โทรล่าสุดล่าสุด): ไฟล์ "C: \ PROGRA ~ 2 \ QGIS3 ~ 1.10 \ apps \ Python37 \ lib \ code.py", บรรทัดที่ 90 ใน runcode exec (code, self.locals) File "", บรรทัด 1 ในไฟล์ "" บรรทัด 98 ในไฟล์ "C: /PROGRA~2/QGIS3~1.10/apps/qgis-ltr /./ python / plugins \ processing \ tools \ general.py" บรรทัด 106 กำลังทำงานอยู่ ส่งคืน Processing.runAlgorithm (algOrName, parameters, onFinish, feedback, context) ไฟล์ "C: /PROGRA~2/QGIS3~1.10/apps/qgis-ltr /./ python / plugins \ processing \ core \ Processing.py", บรรทัด 181 ใน runAlgorithm เพิ่ม QgsProcessingException (msg) _core.QgsProcessingException: มีข้อผิดพลาดในการเรียกใช้อัลกอริทึม

สร้างตารางในฐานข้อมูล PostGIS ของฉัน แต่ตารางว่างเปล่าและมีเฉพาะฟิลด์‚ nummer 'และ‚ geom' ฉันต้องกำหนดฟิลด์ไว้ที่ใดที่หนึ่งในพารามิเตอร์หรือไม่? หรือฉันต้องต่อท้ายตารางที่มีฟิลด์อยู่แล้ว?

ฉันพบประวัติที่น่ารู้ แต่ไม่บันทึกเมื่อฉันเรียกใช้ DB Manager และฉันไม่พบปลั๊กอินอื่นที่จะนำเข้าเลเยอร์เวกเตอร์ไปยัง PostGIS คุณอ้างถึงอันไหน

ฉันพบฟังก์ชันนี้ในกล่องเครื่องมือการประมวลผล ฉันรันมันสำเร็จและใช้ข้อความจากประวัติใน Python หลังจากนั้นไม่นานข้อความแสดงข้อผิดพลาด "... มีข้อผิดพลาดในการเรียกใช้อัลกอริทึม" แต่ได้ส่งออกตารางไปยัง PostgreSQL จำนวนฟีเจอร์ถูกต้องและตารางก็ดูเรียบร้อยดี ดังนั้นฉันไม่ค่อยแน่ใจว่าเกิดอะไรขึ้นจริง

คำตอบ

4 Jakob Sep 29 2020 at 14:42

สำหรับบันทึก. ตัวอย่างของฟังก์ชัน Python ที่ใช้ OGR2OGR นอก QGIS ของ OSGEO QGIS dist ฉันใช้ในการเดินดิสก์เพื่อค้นหาไฟล์รูปร่าง 900 ในไดเร็กทอรีแบบเรียกซ้ำและอัปโหลดไปยัง PostGIS โดยไม่มีข้อผิดพลาด เพื่อลดความซับซ้อนของรหัสฉันได้ลบการตั้งชื่อตาราง GUID บางส่วนเพื่อหลีกเลี่ยงชื่อตารางที่ซ้ำกัน

def upload_to_db(shpfile):
    """
    Uploades shape files to PostgreSQL with org2ogr
    :param shpfile: Shapefile to upload to database
    :return: None
    """

    dbname = 'mydb'
    schema = 'myschema'
    host = 'xx.xx.xxx.xx'
    user = 'myuser'
    password = 'mypw'
    port = '5432'

    tablename = f'{os.path.basename(shpfile)}'

    # https://gdal.org/drivers/vector/pg.html
    command = f"""SET PGCLIENTENCODING=LATIN1 && ogr2ogr -f "PostgreSQL" PG:"host={host} dbname={dbname} user={user} password={password} port={port}" "{shpfile}" -nln {schema}.{tablename} -lco geometry_name=geom -lco precision=NO -nlt promote_to_multi -a_srs epsg:25832"""

    #print(command)
    os.system(command)
4 DirkB. Sep 28 2020 at 16:58

คุณมาถูกทางแล้ว:

ในการส่งออก Shapefile จาก QGIS 3 ไปยัง PostGIS ผ่าน pyqgis คุณสามารถใช้รหัสต่อไปนี้:

import processing
PARAMETERS = {'DATABASE':'nameofdatabase','INPUT':'C:\\Users\\yourpath\\shapename.shp|layername=shapename',
    'SHAPE_ENCODING':'utf-8','GTYPE':5,'A_SRS':QgsCoordinateReferenceSystem('EPSG:4326'),'T_SRS':None,'S_SRS':None,
    'SCHEMA':'schemaname','TABLE':'filenameinpostgis','PK':'id','PRIMARY_KEY':'','GEOCOLUMN':'geom','DIM':0,'SIMPLIFY':'',
    'SEGMENTIZE':'','SPAT':None,'CLIP':False,'WHERE':'','GT':'','OVERWRITE':True,'APPEND':False,
    'ADDFIELDS':False,'LAUNDER':False,'INDEX':False,'SKIPFAILURES':False,'PROMOTETOMULTI':True,
    'PRECISION':True,'OPTIONS':''}

processing.run("gdal:importvectorintopostgisdatabaseavailableconnections", PARAMETERS)

เนื่องจากยังมี Plugin สำหรับนำเข้าเลเยอร์เวกเตอร์ไปยัง PostGIS คุณสามารถดำเนินการได้จากนั้นดูรหัสจาก History Protocol

ปลั๊กอินนี้เป็นปลั๊กอิน GDAL จาก Processing Toolbox "Export to PostgreSQL (available connections)"

ปลั๊กอินดูเหมือนต่อไปนี้และอาจจะง่ายกว่าที่จะใช้สิ่งนี้ก่อนและหลังจากตรวจสอบประวัติของกระบวนการที่ดำเนินการแล้วให้ติดตั้งโค้ดของคุณ

นี่คือลิงค์ไปยังเอกสารจากQGIS 2 QGIS 2.6 docs

นี่คือลิงค์ไปยังเอกสารสำหรับQGIS 3 QGIS 3.10 docs

รหัสของคุณกับ:

 'GTYPE': 0

หมายถึงไม่มีรูปทรงเรขาคณิต btw 5 จะเป็นรูปหลายเหลี่ยม

ข้อมูลเพิ่มเติมอยู่ในลิงก์ไปยังเอกสาร QGIS 2 หรือ QGIS 3 เกี่ยวกับพารามิเตอร์