/wwqLyParse/common/subprocess.py

https://github.com/wwqgtxx/wwqLyParse · Python · 96 lines · 72 code · 13 blank · 11 comment · 28 complexity · a4e43772b9e16836c8036bd20de23cb3 MD5 · raw file

  1. #!/usr/bin/env python3.5
  2. # -*- coding: utf-8 -*-
  3. # author wwqgtxx <wwqgtxx@gmail.com>
  4. import subprocess
  5. import logging
  6. import json
  7. # encoding list to fix encoding BUG on windows
  8. fix_encoding = [
  9. 'UTF-8',
  10. 'cp936',
  11. 'cp950',
  12. ]
  13. # try to decode, to fix encoding BUG on windows
  14. def try_decode(raw, no_error=False):
  15. fix_list = fix_encoding
  16. rest = fix_list
  17. while len(rest) > 0:
  18. one = rest[0]
  19. rest = rest[1:]
  20. try:
  21. out = raw.decode(one)
  22. return out
  23. except Exception as e:
  24. if len(rest) < 1:
  25. if no_error:
  26. out = raw.decode(one, 'ignore')
  27. return out
  28. else:
  29. raise e
  30. # try parse json
  31. def try_parse_json(raw_text):
  32. while True:
  33. try:
  34. info = json.loads(raw_text)
  35. return info
  36. except Exception as e:
  37. try:
  38. rest = '{' + raw_text.split('{', 1)[1]
  39. except IndexError:
  40. raise e
  41. if rest == raw_text:
  42. raise
  43. raw_text = rest
  44. def run_subprocess(args, timeout=None, need_stderr=True, **kwargs):
  45. pipe = subprocess.PIPE
  46. logging.debug(args)
  47. p = subprocess.Popen(args, stdout=pipe, stderr=pipe if need_stderr else None, shell=False, **kwargs)
  48. try:
  49. stdout, stderr = p.communicate(timeout=timeout)
  50. except subprocess.TimeoutExpired:
  51. logging.debug("Timeout!!! kill %s" % p)
  52. p.kill()
  53. stdout, stderr = p.communicate()
  54. else:
  55. # try to decode
  56. stdout = try_decode(stdout)
  57. stderr = try_decode(stderr) if need_stderr else None
  58. # print(stdout)
  59. return stdout, stderr
  60. from . import asyncio
  61. async def async_run_subprocess(args, timeout=None, need_stderr=True, **kwargs):
  62. pipe = subprocess.PIPE
  63. logging.debug(args)
  64. # args = subprocess.list2cmdline(args)
  65. p = await asyncio.create_subprocess_exec(*args, stdout=pipe, stderr=pipe if need_stderr else None, **kwargs)
  66. try:
  67. stdout, stderr = await asyncio.wait_for(p.communicate(), timeout=timeout)
  68. except asyncio.TimeoutError:
  69. raise asyncio.CancelledError
  70. else:
  71. # try to decode
  72. stdout = try_decode(stdout)
  73. stderr = try_decode(stderr) if need_stderr else None
  74. # print(stdout)
  75. return stdout, stderr
  76. finally:
  77. try:
  78. p.terminate()
  79. logging.debug("Timeout!!! kill %s" % p)
  80. except:
  81. pass
  82. def safe_print(text):
  83. print((str(text)).encode('gbk', 'ignore').decode('gbk'))