process.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. ###############################################################################
  2. # LokyProcess implementation
  3. #
  4. # authors: Thomas Moreau and Olivier Grisel
  5. #
  6. # based on multiprocessing/process.py (17/02/2017)
  7. # * Add some compatibility function for python2.7 and 3.3
  8. #
  9. import os
  10. import sys
  11. from .compat import BaseProcess
  12. class LokyProcess(BaseProcess):
  13. _start_method = 'loky'
  14. def __init__(self, group=None, target=None, name=None, args=(),
  15. kwargs={}, daemon=None, init_main_module=False,
  16. env=None):
  17. if sys.version_info < (3, 3):
  18. super(LokyProcess, self).__init__(
  19. group=group, target=target, name=name, args=args,
  20. kwargs=kwargs)
  21. self.daemon = daemon
  22. else:
  23. super(LokyProcess, self).__init__(
  24. group=group, target=target, name=name, args=args,
  25. kwargs=kwargs, daemon=daemon)
  26. self.env = {} if env is None else env
  27. self.authkey = self.authkey
  28. self.init_main_module = init_main_module
  29. @staticmethod
  30. def _Popen(process_obj):
  31. if sys.platform == "win32":
  32. from .popen_loky_win32 import Popen
  33. else:
  34. from .popen_loky_posix import Popen
  35. return Popen(process_obj)
  36. if sys.version_info < (3, 3):
  37. def start(self):
  38. '''
  39. Start child process
  40. '''
  41. from multiprocessing.process import _current_process, _cleanup
  42. assert self._popen is None, 'cannot start a process twice'
  43. assert self._parent_pid == os.getpid(), \
  44. 'can only start a process object created by current process'
  45. _cleanup()
  46. self._popen = self._Popen(self)
  47. self._sentinel = self._popen.sentinel
  48. _current_process._children.add(self)
  49. @property
  50. def sentinel(self):
  51. '''
  52. Return a file descriptor (Unix) or handle (Windows) suitable for
  53. waiting for process termination.
  54. '''
  55. try:
  56. return self._sentinel
  57. except AttributeError:
  58. raise ValueError("process not started")
  59. if sys.version_info < (3, 4):
  60. @property
  61. def authkey(self):
  62. return self._authkey
  63. @authkey.setter
  64. def authkey(self, authkey):
  65. '''
  66. Set authorization key of process
  67. '''
  68. self._authkey = AuthenticationKey(authkey)
  69. def _bootstrap(self):
  70. from .context import set_start_method
  71. set_start_method(self._start_method)
  72. super(LokyProcess, self)._bootstrap()
  73. class LokyInitMainProcess(LokyProcess):
  74. _start_method = 'loky_init_main'
  75. def __init__(self, group=None, target=None, name=None, args=(),
  76. kwargs={}, daemon=None):
  77. super(LokyInitMainProcess, self).__init__(
  78. group=group, target=target, name=name, args=args, kwargs=kwargs,
  79. daemon=daemon, init_main_module=True)
  80. #
  81. # We subclass bytes to avoid accidental transmission of auth keys over network
  82. #
  83. class AuthenticationKey(bytes):
  84. def __reduce__(self):
  85. from .context import assert_spawning
  86. try:
  87. assert_spawning(self)
  88. except RuntimeError:
  89. raise TypeError(
  90. 'Pickling an AuthenticationKey object is '
  91. 'disallowed for security reasons'
  92. )
  93. return AuthenticationKey, (bytes(self),)