Fügen Sie mit Python einen Punkt in PostGIS ein

11

Was ist der richtige Weg, um mit Python einen Punkt in eine PostGIS-Datenbank einzufügen?

Adam Matan
quelle

Antworten:

21

Installieren Sie zunächst das Paket psycopg2 , eine Pythonic-Schnittstelle für PostgreSQL.

Verwenden Sie dann ST_MakePoint:

>>> import psycopg2
>>> conn = psycopg2.connect(dbname=..., port=..., user=...,
                            password=..., host=...)
>>> cur = conn.cursor()
>>> x, y, z, = 32, 34, 0
>>> cur.execute("SELECT ST_SetSRID(ST_MakePoint(%s, %s, %s),4326);", (x, y, z))
>>> cur.fetchall()
[('01010000A0E6100000000000000000404000000000000041400000000000000000',)]

ST_AsText kann verwendet werden, um die Werte zu validieren:

>>> cur.execute("SELECT ST_AsText(ST_SetSRID(ST_MakePoint(%s, %s, %s),4326));", (x, y, z))
>>> cur.fetchall()
[('POINT Z (32 34 0)',)]

Anmerkungen

  • Denken Sie daran, das (lat, lon)ist (y, x)nicht (x, y).
  • Verwenden Sie immer Parameter anstelle von Zeichenfolgenmanipulationen, um eine SQL-Injection zu verhindern . In diesen Beispielen haben wir (x, y, z)am Ende getupft , psycopg2damit die Substitution durchgeführt werden kann.
Adam Matan
quelle
20

Bei komplizierteren Geometrien wie LineString- und Polygon-Geometrien können Sie sie mit Shapely verarbeiten und dann als hexadezimal codiertes WKB durch psycopg2 leiten. Beachten Sie, dass Shapely 1.3 oder höher erforderlich ist, um den Export von 3D-Geometrien mit der wkb_hexEigenschaft zu handhaben .

import psycopg2
from shapely.geometry import LineString
from shapely import wkb

conn = psycopg2.connect('...')
curs = conn.cursor()

# Make a Shapely geometry
ls = LineString([(2.2, 4.4, 10.2), (3.3, 5.5, 8.4)])
ls.wkt  # LINESTRING Z (2.2 4.4 10.2, 3.3 5.5 8.4)
ls.wkb_hex  # 0102000080020000009A999999999901409A999999999911406666666666662440666666...

# Send it to PostGIS
curs.execute('CREATE TEMP TABLE my_lines(geom geometry, name text)')
curs.execute(
    'INSERT INTO my_lines(geom, name)'
    'VALUES (ST_SetSRID(%(geom)s::geometry, %(srid)s), %(name)s)',
    {'geom': ls.wkb_hex, 'srid': 4326, 'name': 'First Line'})

conn.commit()  # save data

# Fetch the data from PostGIS, reading hex-encoded WKB into a Shapely geometry
curs.execute('SELECT name, geom FROM my_lines')
for name, geom_wkb in curs:
    geom = wkb.loads(geom_wkb, hex=True)
    print('{0}: {1}'.format(name, geom.wkt))
# First Line: LINESTRING Z (2.2 4.4 10.2, 3.3 5.5 8.4)

Beachten Sie außerdem, dass Ähnliches durch Senden der WKT der Geometrie erreicht werden kann. Da diese jedoch in Text konvertiert wird, ist sie verlustbehaftet und kann die Genauigkeit verringern. Das Übertragen von Geometrien als hexadezimal codiertes WKB ist verlustfrei und behält die genaue Genauigkeit jeder Koordinate bei.

Mike T.
quelle
Ausgezeichnet, vielen Dank! Ich frage mich, ob es einen Leistungsunterschied zwischen diesen beiden Ansätzen gibt.
Adam Matan
Es gibt einen Leistungsvorteil von 10% beim Erstellen von Punkten ST_MakePoint, was sich hervorragend für Punktgeometrien eignet. Das Erstellen komplexerer Geometrietypen ist mit Shapely jedoch im Allgemeinen einfacher.
Mike T