¿Cuál es la forma correcta de insertar un punto en una base de datos PostGIS usando Python?
¿Cuál es la forma correcta de insertar un punto en una base de datos PostGIS usando Python?
Respuestas:
Primero, instale el paquete psycopg2 , una interfaz Pythonic para PostgreSQL.
Luego, use 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
se puede usar para validar los valores:
>>> cur.execute("SELECT ST_AsText(ST_SetSRID(ST_MakePoint(%s, %s, %s),4326));", (x, y, z))
>>> cur.fetchall()
[('POINT Z (32 34 0)',)]
Notas
(lat, lon)
es (y, x)
, no (x, y)
.(x, y, z)
al final para que psycopg2
pueda manejar la sustitución.Para geometrías más complicadas, como las geometrías LineString y Polygon, puede manejarlas con Shapely, luego pasarlas a través de psycopg2 como WKB codificado en hexadecimal. Tenga en cuenta que se requiere Shapely 1.3 o posterior para manejar la exportación de geometrías 3D con la wkb_hex
propiedad.
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)
Además, tenga en cuenta que se puede lograr algo similar enviando el WKT de la geometría, sin embargo, dado que se convierte en texto, tiene pérdidas y puede reducir los ángulos de precisión. La transferencia de geometrías como WKB codificado en hexadecimal no tiene pérdidas y conserva la precisión exacta de cada coordenada.
ST_MakePoint
, lo cual es ideal para geometrías de puntos. Sin embargo, construir tipos de geometría más complejos generalmente será más simple con Shapely.