[GRASS-dev] [GRASS GIS] #2134: Create a general exit-safe interface to C libraries
GRASS GIS
trac at osgeo.org
Sat Nov 23 11:24:36 PST 2013
#2134: Create a general exit-safe interface to C libraries
--------------------------------------------------+-------------------------
Reporter: wenzeslaus | Owner: grass-dev@…
Type: enhancement | Status: new
Priority: normal | Milestone: 7.0.0
Component: Python ctypes | Version: svn-trunk
Keywords: G_fatal_error, exit, multiprocessing | Platform: All
Cpu: Unspecified |
--------------------------------------------------+-------------------------
Comment(by huhabla):
I have attached a new RPC server that is able to instantiate a persistent
PyGRASS object in a remote process that can be accessed using an RPC
interface, have a look at the attached file
[[attachment:pygrass_rpc_interface.py]].
To get it work i needed to patch the PyGRASS raster info object to avoid
C-pointer that can not be pickled, see [[attachment:pygrass_raster.diff]].
IMHO PyGRASS should avoid pointer and should use ctypes.byref() to pass
pointers to GRASS C-functions. I think (i am not sure about this) that
avoiding ctypes.pointer() may reduce memory leaks as well if objects like
Cell_head() of Range() are managed by the Python garbage collector?
Here an example how to use the PyGRASS RPC interface, reading some raster
map info's and all rows:
{{{
#!python
if __name__ == '__main__':
import grass.script as grassscript
import grass.pygrass.raster as pygrass
grassscript.use_temp_region()
grassscript.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
t=1.0, b=0.0, res=10.0, res3=10.0)
grassscript.run_command("r.mapcalc", expression="test = row()",
overwrite=True, quiet=True)
# Start the server and create a RasterRow remote object
# that is initialized with the raster map name
kargs = {"name":"test"}
server = RPCServer(pygrass.RasterRow, kargs)
# Get some raster map info
info = server.get_property("info")
print "Rows:", info.rows
print "Cols:", info.cols
print "N:", info.north
print "S:", info.south
print "E:", info.east
print "W:", info.west
# Open the raster map for row access
kargs = {}
server.call("open", kargs)
# Read all rows
for row in xrange(info.rows):
kargs = {"row":row}
ret = server.call("get_row", kargs)
print "Row:", row, ret
# Close the raster map
kargs = {}
server.call("close", kargs)
grassscript.del_temp_region()
}}}
Result:
{{{
GRASS 7.0.svn (nc_spm_08):~/src > python pygrass_rpc_interface.py
Rows: 8
Cols: 12
N: 80.0
S: 0.0
E: 120.0
W: 0.0
Row: 0 [1 1 1 1 1 1 1 1 1 1 1 1]
Row: 1 [2 2 2 2 2 2 2 2 2 2 2 2]
Row: 2 [3 3 3 3 3 3 3 3 3 3 3 3]
Row: 3 [4 4 4 4 4 4 4 4 4 4 4 4]
Row: 4 [5 5 5 5 5 5 5 5 5 5 5 5]
Row: 5 [6 6 6 6 6 6 6 6 6 6 6 6]
Row: 6 [7 7 7 7 7 7 7 7 7 7 7 7]
Row: 7 [8 8 8 8 8 8 8 8 8 8 8 8]
}}}
IMHO the RPC interface design should provide a blueprint how to implement
a remote digitizer using PyGRASS to access vector or raster maps. I hope
that most of the PyGRASS functionality will be accessible using this
approach.
Note: with this approach you will create a subprocess for each raster or
vector map that should be modified. Each subprocess will manage only one
object. The subprocess can manage several objects by using a session id.
But IMHO this is not a good idea. In case one object calls G_fatal_error()
or segfaults, all other objects will be killed as well.
PyGRASS may need more patching to make the objects that will be exchanged
between client and server picklable (see PyGRASS raster info object patch
[[attachment:pygrass_raster.diff]]).
This RPC interface will not replace the new PyGRASS messenger interface
nor the tgis specific raster info access RPC implementation. Calling
simple C-functions for each map in a space time raster datasets (STRDS)
using an RPC interface is much faster than creating a subprocess and a
raster object for each map in a STRDS.
Hence, there are different solutions for different needs. :)
--
Ticket URL: <http://trac.osgeo.org/grass/ticket/2134#comment:15>
GRASS GIS <http://grass.osgeo.org>
More information about the grass-dev
mailing list