Index: subprocess2.py |
diff --git a/subprocess2.py b/subprocess2.py |
index a00592f4774a83eaa8e697d38c8ab7a921903fa9..37b9b64394a4606a9405dcb2acfaa20b755fa198 100644 |
--- a/subprocess2.py |
+++ b/subprocess2.py |
@@ -462,6 +462,49 @@ def communicate(args, timeout=None, nag_timer=None, nag_max=None, **kwargs): |
return proc.communicate(None, timeout, nag_timer), proc.returncode |
+def communicate_and_stream(args, **kwargs): |
M-A Ruel
2016/03/08 23:54:08
There's a function to do something similar in gcli
|
+ """Same as communicate, but will not just capture, but also stream output |
+ streams while command is running. |
+ |
+ Returns ((stdout, stderr), returncode). |
+ |
+ By default, streams and captures both stdout and stderr. You can silence any |
+ of the streams, but passing std{err,out} special PIPE or VOID, depending on |
+ whether you want it captured or completely ignored. |
+ |
+ This useful for commands that take time to run, such that it's useful to both |
+ capture output but also steram as parent process std{out,err}. |
+ """ |
+ # communicate method above won't capture anything if std{err,out} is callable. |
+ # So, capture it ourselves essentially the same way. |
+ # Aslo, because callbacks are called in asynchroneous thread, we can stream |
Paweł Hajdan Jr.
2016/03/08 23:52:24
nit: Aslo -> Also ; asynchroneous -> asynchronous
|
+ # output directly with simple labmbda, no need for yet another thread. |
+ def combine_funcs(f1, f2): |
+ def f(x): |
+ f1(x) |
+ f2(x) |
+ return f |
+ |
+ result = {} |
+ for stream in ('stderr', 'stdout'): |
+ if stream in kwargs: |
+ # Don't stream/capture streams that user specified explicitely. |
Paweł Hajdan Jr.
2016/03/08 23:52:24
nit: explicitely -> explicitly
|
+ continue |
+ result[stream] = [] # Container to hold results data chunks. |
+ kwargs[stream] = combine_funcs( |
+ result[stream].append, |
+ getattr(sys, stream).write) |
+ |
+ (out, err), returncode = communicate(args, **kwargs) |
+ if 'stderr' in result: |
+ assert not err |
+ err = ''.join(result['stderr']) |
+ if 'stdout' in result: |
+ assert not out |
+ out = ''.join(result['stdout']) |
+ return (out, err), returncode |
+ |
+ |
def call(args, **kwargs): |
"""Emulates subprocess.call(). |