|
1 """ |
|
2 |
|
3 """ |
|
4 |
|
5 import os, sys |
|
6 import subprocess |
|
7 import py |
|
8 from subprocess import Popen, PIPE |
|
9 |
|
10 def cmdexec(cmd): |
|
11 """ return unicode output of executing 'cmd' in a separate process. |
|
12 |
|
13 raise cmdexec.ExecutionFailed exeception if the command failed. |
|
14 the exception will provide an 'err' attribute containing |
|
15 the error-output from the command. |
|
16 if the subprocess module does not provide a proper encoding/unicode strings |
|
17 sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'. |
|
18 """ |
|
19 process = subprocess.Popen(cmd, shell=True, |
|
20 universal_newlines=True, |
|
21 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
22 out, err = process.communicate() |
|
23 if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not |
|
24 try: |
|
25 default_encoding = sys.getdefaultencoding() # jython may not have it |
|
26 except AttributeError: |
|
27 default_encoding = sys.stdout.encoding or 'UTF-8' |
|
28 out = unicode(out, process.stdout.encoding or default_encoding) |
|
29 err = unicode(err, process.stderr.encoding or default_encoding) |
|
30 status = process.poll() |
|
31 if status: |
|
32 raise ExecutionFailed(status, status, cmd, out, err) |
|
33 return out |
|
34 |
|
35 class ExecutionFailed(py.error.Error): |
|
36 def __init__(self, status, systemstatus, cmd, out, err): |
|
37 Exception.__init__(self) |
|
38 self.status = status |
|
39 self.systemstatus = systemstatus |
|
40 self.cmd = cmd |
|
41 self.err = err |
|
42 self.out = out |
|
43 |
|
44 def __str__(self): |
|
45 return "ExecutionFailed: %d %s\n%s" %(self.status, self.cmd, self.err) |
|
46 |
|
47 # export the exception under the name 'py.process.cmdexec.Error' |
|
48 cmdexec.Error = ExecutionFailed |
|
49 try: |
|
50 ExecutionFailed.__module__ = 'py.process.cmdexec' |
|
51 ExecutionFailed.__name__ = 'Error' |
|
52 except (AttributeError, TypeError): |
|
53 pass |