-
Notifications
You must be signed in to change notification settings - Fork 814
/
Copy pathsubprocess_output.py
63 lines (49 loc) · 1.89 KB
/
subprocess_output.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# (C) Datadog, Inc. 2010-2016
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)
# stdlib
from functools import wraps
import logging
import subprocess
import tempfile
log = logging.getLogger(__name__)
class SubprocessOutputEmptyError(Exception):
pass
def get_subprocess_output(command, log, raise_on_empty_output=True):
"""
Run the given subprocess command and return its output. Raise an Exception
if an error occurs.
"""
return subprocess_output(command, raise_on_empty_output)
def subprocess_output(command, raise_on_empty_output):
"""
Run the given subprocess command and return its output. This is a private method
and should not be called directly, use `get_subprocess_output` instead.
"""
# Use tempfile, allowing a larger amount of memory. The subprocess.Popen
# docs warn that the data read is buffered in memory. They suggest not to
# use subprocess.PIPE if the data size is large or unlimited.
with tempfile.TemporaryFile() as stdout_f, tempfile.TemporaryFile() as stderr_f:
proc = subprocess.Popen(command, stdout=stdout_f, stderr=stderr_f)
proc.wait()
stderr_f.seek(0)
err = stderr_f.read()
stdout_f.seek(0)
output = stdout_f.read()
if not output and raise_on_empty_output:
raise SubprocessOutputEmptyError("get_subprocess_output expected output but had none.")
return (output, err, proc.returncode)
def log_subprocess(func):
"""
Wrapper around subprocess to log.debug commands.
"""
@wraps(func)
def wrapper(*params, **kwargs):
fc = "%s(%s)" % (func.__name__, ', '.join(
[a.__repr__() for a in params] +
["%s = %s" % (a, b) for a, b in kwargs.items()]
))
log.debug("%s called" % fc)
return func(*params, **kwargs)
return wrapper
subprocess.Popen = log_subprocess(subprocess.Popen)