Insérer un point dans PostGIS à l'aide de Python

11

Quelle est la bonne façon d'insérer un point dans une base de données PostGIS à l'aide de Python?

Adam Matan
la source

Réponses:

21

Tout d'abord, installez le package psycopg2 , une interface Pythonic pour PostgreSQL.

Ensuite, utilisez 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 peut être utilisé pour valider les valeurs:

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

Remarques

  • Rappelez - vous que (lat, lon)est (y, x), non (x, y).
  • Utilisez toujours des paramètres, plutôt que des manipulations de chaînes, pour empêcher l'injection SQL . Dans cet exemple, nous avons tuplé (x, y, z)à la fin afin de psycopg2pouvoir gérer la substitution.
Adam Matan
la source
20

Pour les géométries plus compliquées, telles que les géométries LineString et Polygon, vous pouvez les gérer avec Shapely, puis les passer via psycopg2 en tant que WKB codé hexadécimal. Notez que Shapely 1.3 ou version ultérieure est requis pour gérer l'exportation des géométries 3D avec la wkb_hexpropriété.

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)

Notez en outre que la même chose peut être accomplie en envoyant le WKT de la géométrie, mais comme il est converti en texte, il est avec perte et peut réduire les angströms de précision. Le transfert de géométries au format WKB codé hexadécimal est sans perte et préserve la précision exacte de chaque coordonnée.

Mike T
la source
Excellent merci! Je me demande s'il y a une différence de performances entre ces deux approches.
Adam Matan
Il y a un avantage de performance de 10% avec les points de construction ST_MakePoint, ce qui est idéal pour les géométries de points. Cependant, la création de types de géométrie plus complexes sera généralement plus simple avec Shapely.
Mike T