[GRASS-SVN] r70324 - grass/trunk/lib/python/script

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Jan 9 06:43:57 PST 2017


Author: wenzeslaus
Date: 2017-01-09 06:43:57 -0800 (Mon, 09 Jan 2017)
New Revision: 70324

Modified:
   grass/trunk/lib/python/script/Makefile
   grass/trunk/lib/python/script/core.py
Log:
pythonlib: set_capture_stderr to send subprocess stderr to sys.stderr

This is useful for Python tab/shell in GUI and Jupyter/IPython Notebooks.

Implementation follows existing set_raise_on_error().


Modified: grass/trunk/lib/python/script/Makefile
===================================================================
--- grass/trunk/lib/python/script/Makefile	2017-01-09 12:51:37 UTC (rev 70323)
+++ grass/trunk/lib/python/script/Makefile	2017-01-09 14:43:57 UTC (rev 70324)
@@ -5,7 +5,7 @@
 
 DSTDIR = $(ETC)/python/grass/script
 
-MODULES = core db raster raster3d vector array setup task utils
+MODULES = core db raster raster3d vector array setup task utils parallel
 
 PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
 PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)

Modified: grass/trunk/lib/python/script/core.py
===================================================================
--- grass/trunk/lib/python/script/core.py	2017-01-09 12:51:37 UTC (rev 70323)
+++ grass/trunk/lib/python/script/core.py	2017-01-09 14:43:57 UTC (rev 70324)
@@ -78,6 +78,7 @@
 
 
 raise_on_error = False  # raise exception instead of calling fatal()
+_capture_stderr = False  # capture stderr of subprocesses if possible
 
 
 def call(*args, **kwargs):
@@ -405,8 +406,16 @@
 
     :raises: ``CalledModuleError`` when module returns non-zero return code
     """
+    if _capture_stderr and 'stderr' not in kwargs.keys():
+        kwargs['stderr'] = PIPE
     ps = start_command(*args, **kwargs)
-    returncode = ps.wait()
+    if _capture_stderr:
+        stdout, stderr = ps.communicate()
+        returncode = ps.poll()
+        if returncode:
+            sys.stderr.write(stderr)
+    else:
+        returncode = ps.wait()
     return handle_errors(returncode, returncode, args, kwargs)
 
 
@@ -455,9 +464,13 @@
 
     :return: stdout
     """
+    if _capture_stderr and 'stderr' not in kwargs.keys():
+        kwargs['stderr'] = PIPE
     process = pipe_command(*args, **kwargs)
-    stdout, unused = process.communicate()
+    stdout, stderr = process.communicate()
     returncode = process.poll()
+    if _capture_stderr and returncode:
+        sys.stderr.write(stderr)
     return handle_errors(returncode, stdout, args, kwargs)
 
 
@@ -526,9 +539,13 @@
     """
     # TODO: should we delete it from kwargs?
     stdin = kwargs['stdin']
+    if _capture_stderr and 'stderr' not in kwargs.keys():
+        kwargs['stderr'] = PIPE
     process = feed_command(*args, **kwargs)
-    process.communicate(stdin)
+    unused, stderr = process.communicate(stdin)
     returncode = process.poll()
+    if _capture_stderr and returncode:
+        sys.stderr.write(stderr)
     return handle_errors(returncode, returncode, args, kwargs)
 
 
@@ -668,6 +685,46 @@
     global raise_on_error
     return raise_on_error
 
+
+# TODO: solve also warnings (not printed now)
+def set_capture_stderr(capture=True):
+    """Enable capturing standard error output of modules and print it.
+
+    By default, standard error output (stderr) of child processes shows
+    in the same place as output of the parent process. This may not
+    always be the same place as ``sys.stderr`` is written.
+    After calling this function, functions in the ``grass.script``
+    package will capture the stderr of child processes and pass it
+    to ``sys.stderr`` if there is an error.
+
+    .. note::
+
+        This is advantages for interactive shells such as the one in GUI
+        and interactive notebooks such as Jupyer Notebook.
+
+    The capturing can be applied only in certain cases, for example
+    in case of run_command() it is applied because run_command() nor
+    its callers do not handle the streams, however feed_command()
+    cannot do capturing because its callers handle the streams.
+
+    The previous state is returned. Passing ``False`` disables the
+    capturing.
+
+    .. versionadded:: 7.4
+    """
+    global _capture_stderr
+    tmp = _capture_stderr
+    _capture_stderr = capture
+    return tmp
+
+def get_capture_stderr():
+    """Return True if stderr is captured, False otherwise.
+
+    See set_capture_stderr().
+    """
+    global _capture_stderr
+    return _capture_stderr
+
 # interface to g.parser
 
 



More information about the grass-commit mailing list