SpatiaLite and Python
shortly telling my first-hand experience
2011 January 10|
Quick intro:
I recently posted a short story telling my experiences about
SpatiaLite and Java (Xerial JDBC connector).
Conforming to a politically correct equal opportunities approach I'll now tell you the same story yet again: this time using Python and the pyspatialite connector. Python too is widespread: lots of developers use Python as their main development language. That's not all: the very popular QGIS [the most commonly used open source desktop GIS] strongly supports Python integration: lots of QGIS plugins are written in Python. And I recently noticed an increasing number of posts on the SpatiaLite User Group mailing list [http://groups.google.com/group/spatialite-users] about obscure issues and conflicts related to QGIS Python plugins. So I'm quite sure that an up-to-data review about this topic surely is welcome for any people interested in both SpatiaLite and QGIS. |
Test environment
|
$ python setup.py build ... verbose output follows [suppressed] ... $ su # python setup.py install |
|
Caveat The most recent QGIS versions (1.6 / 1.7 trunk) are actually using SpatiaLite v.2.4.0 so any Python plugin using the previous v.2.3.1 can easily cause conflicts due to version incompatilibiles.And this fully accounts for any issue noticed by QGIS users. |
Patching setup.py
|
def get_amalgamation(): """Download the Spatialite amalgamation if it isn't there, already.""" if os.path.exists(AMALGAMATION_ROOT): return os.mkdir(AMALGAMATION_ROOT) print "Downloading amalgation." # find out what's current amalgamation ZIP file download_page = urllib.urlopen("http://www.gaia-gis.it/spatialite-2.4.0-4/sources.html").read() pattern = re.compile("(libspatialite-amalgamation.*?\.zip)") download_file = pattern.findall(download_page)[0] amalgamation_url = "http://www.gaia-gis.it/spatialite-2.4.0-4/"+ download_file zip_dir = string.replace(download_file,'.zip','') # and download it urllib.urlretrieve(amalgamation_url, "tmp.zip") |
Testing pyspatialite (full success)
|
# importing pyspatialite from pyspatialite import dbapi2 as db # creating/connecting the test_db conn = db.connect('test_db.sqlite') # creating a Cursor cur = conn.cursor() # testing library versions rs = cur.execute('SELECT sqlite_version(), spatialite_version()') for row in rs: msg = "> SQLite v%s Spatialite v%s" % (row[0], row[1]) print msg # initializing Spatial MetaData # using v.2.4.0 this will automatically create # GEOMETRY_COLUMNS and SPATIAL_REF_SYS sql = 'SELECT InitSpatialMetadata()' cur.execute(sql) # creating a POINT table sql = 'CREATE TABLE test_pt (' sql += 'id INTEGER NOT NULL PRIMARY KEY,' sql += 'name TEXT NOT NULL)' cur.execute(sql) # creating a POINT Geometry column sql = "SELECT AddGeometryColumn('test_pt', " sql += "'geom', 4326, 'POINT', 'XY')" cur.execute(sql) # creating a LINESTRING table sql = 'CREATE TABLE test_ln (' sql += 'id INTEGER NOT NULL PRIMARY KEY,' sql += 'name TEXT NOT NULL)' cur.execute(sql) # creating a LINESTRING Geometry column sql = "SELECT AddGeometryColumn('test_ln', " sql += "'geom', 4326, 'LINESTRING', 'XY')" cur.execute(sql) # creating a POLYGON table sql = 'CREATE TABLE test_pg (' sql += 'id INTEGER NOT NULL PRIMARY KEY,' sql += 'name TEXT NOT NULL)' cur.execute(sql) # creating a POLYGON Geometry column sql = "SELECT AddGeometryColumn('test_pg', " sql += "'geom', 4326, 'POLYGON', 'XY')" cur.execute(sql) # inserting some POINTs # please note well: SQLite is ACID and Transactional # so (to get best performance) the whole insert cycle # will be handled as a single TRANSACTION for i in range(100000): name = "test POINT #%d" % (i+1) geom = "GeomFromText('POINT(" geom += "%f " % (i / 1000.0) geom += "%f" % (i / 1000.0) geom += ")', 4326)" sql = "INSERT INTO test_pt (id, name, geom) " sql += "VALUES (%d, '%s', %s)" % (i+1, name, geom) cur.execute(sql) conn.commit() # checking POINTs sql = "SELECT DISTINCT Count(*), ST_GeometryType(geom), " sql += "ST_Srid(geom) FROM test_pt" rs = cur.execute(sql) for row in rs: msg = "> Inserted %d entities of type " % (row[0]) msg += "%s SRID=%d" % (row[1], row[2]) print msg # inserting some LINESTRINGs for i in range(100000): name = "test LINESTRING #%d" % (i+1) geom = "GeomFromText('LINESTRING(" if (i%2) == 1: # odd row: five points geom += "-180.0 -90.0, " geom += "%f " % (-10.0 - (i / 1000.0)) geom += "%f, " % (-10.0 - (i / 1000.0)) geom += "%f " % (10.0 + (i / 1000.0)) geom += "%f" % (10.0 + (i / 1000.0)) geom += ", 180.0 90.0" else: # even row: two points geom += "%f " % (-10.0 - (i / 1000.0)) geom += "%f, " % (-10.0 - (i / 1000.0)) geom += "%f " % (10.0 + (i / 1000.0)) geom += "%f" % (10.0 + (i / 1000.0)) geom += ")', 4326)" sql = "INSERT INTO test_ln (id, name, geom) " sql += "VALUES (%d, '%s', %s)" % (i+1, name, geom) cur.execute(sql) conn.commit() # checking LINESTRINGs sql = "SELECT DISTINCT Count(*), ST_GeometryType(geom), " sql += "ST_Srid(geom) FROM test_ln" rs = cur.execute(sql) for row in rs: msg = "> Inserted %d entities of type " % (row[0]) msg += "%s SRID=%d" % (row[1], row[2]) print msg # inserting some POLYGONs for i in range(100000): name = "test POLYGON #%d" % (i+1) geom = "GeomFromText('POLYGON((" geom += "%f " % (-10.0 - (i / 1000.0)) geom += "%f, " % (-10.0 - (i / 1000.0)) geom += "%f " % (10.0 + (i / 1000.0)) geom += "%f, " % (-10.0 - (i / 1000.0)) geom += "%f " % (10.0 + (i / 1000.0)) geom += "%f, " % (10.0 + (i / 1000.0)) geom += "%f " % (-10.0 - (i / 1000.0)) geom += "%f, " % (10.0 + (i / 1000.0)) geom += "%f " % (-10.0 - (i / 1000.0)) geom += "%f" % (-10.0 - (i / 1000.0)) geom += "))', 4326)" sql = "INSERT INTO test_pg (id, name, geom) " sql += "VALUES (%d, '%s', %s)" % (i+1, name, geom) cur.execute(sql) conn.commit() # checking POLYGONs sql = "SELECT DISTINCT Count(*), ST_GeometryType(geom), " sql += "ST_Srid(geom) FROM test_pg" rs = cur.execute(sql) for row in rs: msg = "> Inserted %d entities of type " % (row[0]) msg += "%s SRID=%d" % (row[1], row[2]) print msg rs.close() conn.close() quit() |
| $ python spatialite_sample.py |