cmdexec.py 1.8 KB

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