Support passing stdout and stderr in start_standing_subprocess (#934)
diff --git a/mobly/utils.py b/mobly/utils.py
index 5b72c08..f567c32 100644
--- a/mobly/utils.py
+++ b/mobly/utils.py
@@ -507,7 +507,13 @@
return process.returncode, out, err
-def start_standing_subprocess(cmd, shell=False, env=None):
+def start_standing_subprocess(
+ cmd,
+ shell=False,
+ env=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+):
"""Starts a long-running subprocess.
This is not a blocking call and the subprocess started by it should be
@@ -519,10 +525,14 @@
Args:
cmd: string, the command to start the subprocess with.
shell: bool, True to run this command through the system shell,
- False to invoke it directly. See subprocess.Proc() docs.
+ False to invoke it directly. See subprocess.Popen() docs.
env: dict, a custom environment to run the standing subprocess. If not
specified, inherits the current environment. See subprocess.Popen()
docs.
+ stdout: None, subprocess.PIPE, subprocess.DEVNULL, an existing file
+ descriptor, or an existing file object. See subprocess.Popen() docs.
+ stderr: None, subprocess.PIPE, subprocess.DEVNULL, an existing file
+ descriptor, or an existing file object. See subprocess.Popen() docs.
Returns:
The subprocess that was started.
@@ -531,8 +541,8 @@
proc = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
+ stdout=stdout,
+ stderr=stderr,
shell=shell,
env=env,
)
diff --git a/tests/mobly/utils_test.py b/tests/mobly/utils_test.py
index 4fd55ce..2891b92 100755
--- a/tests/mobly/utils_test.py
+++ b/tests/mobly/utils_test.py
@@ -406,6 +406,36 @@
env=mock_env,
)
+ @mock.patch('subprocess.Popen')
+ def test_start_standing_subproc_with_custom_stdout(self, mock_popen):
+ mock_stdout = mock.MagicMock(spec=io.TextIOWrapper)
+
+ utils.start_standing_subprocess(self.sleep_cmd(0.01), stdout=mock_stdout)
+
+ mock_popen.assert_called_with(
+ self.sleep_cmd(0.01),
+ stdin=subprocess.PIPE,
+ stdout=mock_stdout,
+ stderr=subprocess.PIPE,
+ shell=False,
+ env=None,
+ )
+
+ @mock.patch('subprocess.Popen')
+ def test_start_standing_subproc_with_custom_stderr(self, mock_popen):
+ mock_stderr = mock.MagicMock(spec=io.TextIOWrapper)
+
+ utils.start_standing_subprocess(self.sleep_cmd(0.01), stderr=mock_stderr)
+
+ mock_popen.assert_called_with(
+ self.sleep_cmd(0.01),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=mock_stderr,
+ shell=False,
+ env=None,
+ )
+
def test_stop_standing_subproc(self):
p = utils.start_standing_subprocess(self.sleep_cmd(4))
utils.stop_standing_subprocess(p)