#2326: Command functions in grass.script.core miss a correct error reporting
-------------------------+--------------------------------------------------
Reporter: wenzeslaus | Owner: grass-dev@…
Type: enhancement | Status: new
Priority: normal | Milestone: 7.1.0
Component: Python | Version: svn-trunk
Keywords: script | Platform: All
Cpu: Unspecified |
-------------------------+--------------------------------------------------
There is a lot of functions in grass.core which can run a GRASS module.
One is allowing this the other that but none of them is actually providing
the convenient interface to a (the most?) common case where you not only
want stdout as a string (and perhaps stdin as a string too) but also you
want an error message to be reported in program(mer)-friendly way.
The later is actually a motivation for this ticket because I see this as a
critical issue which is very dangerous for
[https://gis.stackexchange.com/questions/99773/problems-running-grass-
mapcalc/ beginners] (writing scripts with `run_command` or others) and not
checking the return code or stderr with an expectation that the function
will report the error (in Python sense, thus raising an exception). And
this issue is valid also for advanced GRASS Python programmers/users
because there is a need to still check output of each command and report
error manually. Moreover, the current state goes against the philosophy of
C library which takes the burden of dealing with errors from the
programmer.
The fact is that you then and up with implementing your own
`start_command` wrappers. For example,
[http://trac.osgeo.org/grass/browser/grass/trunk/gui/wxpython/animation/provider.py#L734
animation tool] uses its own function based on `start_command` returning
return code (`int`), stdout (`str`), stderr (`str`):
{{{
#!python
def read2_command(*args, **kwargs):
kwargs['stdout'] = gcore.PIPE
kwargs['stderr'] = gcore.PIPE
ps = gcore.start_command(*args, **kwargs)
stdout, stderr = ps.communicate()
return ps.returncode, stdout, stderr
}}}
I recently used this code inside some function which gets stdin as string,
uses stdout and in case of non-zero return code throws/raises an exception
(`RuntimeError`) with error message containing module name and stderr:
{{{
#!python
proc = gcore.start_command('m.proj', input='-', separator=' , ',
flags='od',
stdin=gcore.PIPE,
stdout=gcore.PIPE,
stderr=gcore.PIPE)
proc.stdin.write(proj_in)
proc.stdin.close()
proc.stdin = None
proj_out, errors = proc.communicate()
if proc.returncode:
raise RuntimeError("m.proj error: %s" % errors)
}}}
I would probably just commit the combination of the code samples above as
a new function but I want to be sure that it will be right this time. I
don't know whether my requirements are the same of the majority and
finally, I don't know what name to choose for the new function since it
seems that functions in `grass.script.core` already used every possible
name. Also, I'm not sure what is the PyGRASS's answer to this problem.
--
Ticket URL: <http://trac.osgeo.org/grass/ticket/2326>
GRASS GIS <http://grass.osgeo.org>