Skip to content
This repository was archived by the owner on Aug 26, 2020. It is now read-only.

Commit af4c738

Browse files
authored
fix: Revert "change: stream stderr even when capture_error is True (#233)" (#268)
This reverts commit f4d3456.
1 parent ed28a2c commit af4c738

File tree

3 files changed

+12
-75
lines changed

3 files changed

+12
-75
lines changed

src/sagemaker_containers/_process.py

Lines changed: 7 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"""Placeholder docstring"""
1414
from __future__ import absolute_import
1515

16-
import io
1716
import os
1817
import subprocess
1918
import sys
@@ -25,82 +24,30 @@
2524

2625

2726
def create(cmd, error_class, cwd=None, capture_error=False, **kwargs):
28-
"""Create subprocess.Popen object for the given command.
29-
30-
Args:
31-
cmd (list): The command to be run.
32-
error_class (cls): The class to use when raising an exception.
33-
cwd (str): The location from which to run the command (default: None).
34-
If None, this defaults to the ``code_dir`` of the environment.
35-
capture_error (bool): whether or not to direct stderr to a stream
36-
that can later be read (default: False).
37-
**kwargs: Extra arguments that are passed to the subprocess.Popen constructor.
38-
39-
Returns:
40-
subprocess.Popen: the process for the given command
41-
42-
Raises:
43-
error_class: if there is an exception raised when creating the process
44-
"""
27+
"""Placeholder docstring"""
4528
try:
46-
# Capture both so that we can control the order of when stdout and stderr are streamed
47-
stdout = subprocess.PIPE if capture_error else None
4829
stderr = subprocess.PIPE if capture_error else None
49-
5030
return subprocess.Popen(
51-
cmd, env=os.environ, cwd=cwd or _env.code_dir, stdout=stdout, stderr=stderr, **kwargs
31+
cmd, env=os.environ, cwd=cwd or _env.code_dir, stderr=stderr, **kwargs
5232
)
5333
except Exception as e: # pylint: disable=broad-except
5434
six.reraise(error_class, error_class(e), sys.exc_info()[2])
5535

5636

5737
def check_error(cmd, error_class, capture_error=False, **kwargs):
5838
# type: (List[str], type, bool, Mapping[str, object]) -> subprocess.Popen
59-
"""Run a commmand, raising an exception if there is an error.
60-
61-
Args:
62-
cmd (list): The command to be run.
63-
error_class (cls): The class to use when raising an exception.
64-
capture_error (bool): whether or not to include stderr in
65-
the exception message (default: False). In either case,
66-
stderr is streamed to the process's output.
67-
**kwargs: Extra arguments that are passed to the subprocess.Popen constructor.
68-
69-
Returns:
70-
subprocess.Popen: the process for the given command
71-
72-
Raises:
73-
error_class: if there is an exception raised when creating the process
74-
"""
39+
"""Placeholder docstring"""
7540
process = create(cmd, error_class, capture_error=capture_error, **kwargs)
7641

7742
if capture_error:
78-
# Create a copy of stderr so that it can be read after being streamed
79-
with io.BytesIO() as stderr_copy:
80-
return_code = process.poll()
81-
while return_code is None:
82-
stdout = process.stdout.readline()
83-
sys.stdout.write(stdout.decode("utf-8"))
84-
stderr = process.stderr.readline()
85-
sys.stdout.write(stderr.decode("utf-8"))
86-
87-
stderr_copy.write(stderr)
88-
return_code = process.poll()
89-
90-
# Read the rest of stdout/stdin because readline() reads only one line at a time
91-
stdout = process.stdout.read()
92-
sys.stdout.write(stdout.decode("utf-8"))
93-
stderr = process.stderr.read()
94-
sys.stdout.write(stderr.decode("utf-8"))
95-
96-
stderr_copy.write(stderr)
97-
full_stderr = stderr_copy.getvalue()
43+
_, stderr = process.communicate()
44+
return_code = process.poll()
9845
else:
99-
full_stderr = None
46+
stderr = None
10047
return_code = process.wait()
10148

10249
if return_code:
103-
raise error_class(return_code=return_code, cmd=" ".join(cmd), output=full_stderr)
50+
raise error_class(return_code=return_code, cmd=" ".join(cmd), output=stderr)
10451
return process
10552

10653

test/unit/test_mpi.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ def test_mpi_master_run(training_env, popen, policy, ssh_client, path_exists):
166166
],
167167
cwd=_env.code_dir,
168168
env=ANY,
169-
stdout=None,
170169
stderr=None,
171170
)
172171

@@ -262,7 +261,6 @@ def test_mpi_master_run_python(
262261
],
263262
cwd=_env.code_dir,
264263
env=ANY,
265-
stdout=None,
266264
stderr=None,
267265
)
268266

test/unit/test_process.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,20 @@ def test_run_bash(log, popen, entry_point_type_script):
6767
_process.ProcessRunner("launcher.sh", ["--lr", "1 3"], {}).run()
6868

6969
cmd = ["/bin/sh", "-c", "./launcher.sh --lr '1 3'"]
70-
popen.assert_called_with(cmd, cwd=_env.code_dir, env=os.environ, stdout=None, stderr=None)
70+
popen.assert_called_with(cmd, cwd=_env.code_dir, env=os.environ, stderr=None)
7171
log.assert_called_with(cmd, {})
7272

7373

7474
@patch("subprocess.Popen")
7575
@patch("sagemaker_containers._logging.log_script_invocation")
76-
def test_run_python_capture_error(log, popen, entry_point_type_script):
77-
mock_process = MagicMock()
78-
mock_process.stdout.readline.return_value = b"stdout"
79-
mock_process.stderr.readline.return_value = b"stderr"
80-
mock_process.stdout.read.return_value = b"stdout"
81-
mock_process.stderr.read.return_value = b"stderr"
82-
mock_process.poll.return_value = 1
83-
popen.return_value = mock_process
76+
def test_run_python(log, popen, entry_point_type_script):
77+
popen().communicate.return_value = (None, 0)
8478

8579
with pytest.raises(_errors.ExecuteUserScriptError):
8680
_process.ProcessRunner("launcher.py", ["--lr", "13"], {}).run(capture_error=True)
8781

8882
cmd = [sys.executable, "launcher.py", "--lr", "13"]
89-
popen.assert_called_with(
90-
cmd, cwd=_env.code_dir, env=os.environ, stdout=subprocess.PIPE, stderr=subprocess.PIPE
91-
)
83+
popen.assert_called_with(cmd, cwd=_env.code_dir, env=os.environ, stderr=subprocess.PIPE)
9284
log.assert_called_with(cmd, {})
9385

9486

@@ -99,7 +91,7 @@ def test_run_module(log, popen, entry_point_type_module):
9991
_process.ProcessRunner("module.py", ["--lr", "13"], {}).run()
10092

10193
cmd = [sys.executable, "-m", "module", "--lr", "13"]
102-
popen.assert_called_with(cmd, cwd=_env.code_dir, env=os.environ, stdout=None, stderr=None)
94+
popen.assert_called_with(cmd, cwd=_env.code_dir, env=os.environ, stderr=None)
10395
log.assert_called_with(cmd, {})
10496

10597

0 commit comments

Comments
 (0)