exceptions.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.exceptions
  4. ~~~~~~~~~~~~~~~~~
  5. This module contains all exceptions used by the Celery API.
  6. """
  7. from __future__ import absolute_import, unicode_literals
  8. import numbers
  9. from .five import python_2_unicode_compatible, string_t
  10. from billiard.exceptions import ( # noqa
  11. SoftTimeLimitExceeded, TimeLimitExceeded, WorkerLostError, Terminated,
  12. )
  13. __all__ = [
  14. 'CeleryError', 'CeleryWarning', 'TaskPredicate',
  15. 'SecurityError', 'Ignore', 'QueueNotFound',
  16. 'WorkerShutdown', 'WorkerTerminate',
  17. 'ImproperlyConfigured', 'NotRegistered', 'AlreadyRegistered',
  18. 'TimeoutError', 'MaxRetriesExceededError', 'Retry', 'Reject',
  19. 'TaskRevokedError', 'NotConfigured', 'AlwaysEagerIgnored',
  20. 'InvalidTaskError', 'ChordError', 'CPendingDeprecationWarning',
  21. 'CDeprecationWarning', 'FixupWarning', 'DuplicateNodenameWarning',
  22. 'SoftTimeLimitExceeded', 'TimeLimitExceeded', 'WorkerLostError',
  23. 'Terminated', 'IncompleteStream'
  24. ]
  25. UNREGISTERED_FMT = """\
  26. Task of kind {0} is not registered, please make sure it's imported.\
  27. """
  28. class CeleryError(Exception):
  29. pass
  30. class CeleryWarning(UserWarning):
  31. pass
  32. class SecurityError(CeleryError):
  33. """Security related exceptions.
  34. Handle with care.
  35. """
  36. class TaskPredicate(CeleryError):
  37. pass
  38. @python_2_unicode_compatible
  39. class Retry(TaskPredicate):
  40. """The task is to be retried later."""
  41. #: Optional message describing context of retry.
  42. message = None
  43. #: Exception (if any) that caused the retry to happen.
  44. exc = None
  45. #: Time of retry (ETA), either :class:`numbers.Real` or
  46. #: :class:`~datetime.datetime`.
  47. when = None
  48. def __init__(self, message=None, exc=None, when=None, **kwargs):
  49. from kombu.utils.encoding import safe_repr
  50. self.message = message
  51. if isinstance(exc, string_t):
  52. self.exc, self.excs = None, exc
  53. else:
  54. self.exc, self.excs = exc, safe_repr(exc) if exc else None
  55. self.when = when
  56. Exception.__init__(self, exc, when, **kwargs)
  57. def humanize(self):
  58. if isinstance(self.when, numbers.Real):
  59. return 'in {0.when}s'.format(self)
  60. return 'at {0.when}'.format(self)
  61. def __str__(self):
  62. if self.message:
  63. return self.message
  64. if self.excs:
  65. return 'Retry {0}: {1}'.format(self.humanize(), self.excs)
  66. return 'Retry {0}'.format(self.humanize())
  67. def __reduce__(self):
  68. return self.__class__, (self.message, self.excs, self.when)
  69. RetryTaskError = Retry # XXX compat
  70. class Ignore(TaskPredicate):
  71. """A task can raise this to ignore doing state updates."""
  72. @python_2_unicode_compatible
  73. class Reject(TaskPredicate):
  74. """A task can raise this if it wants to reject/re-queue the message."""
  75. def __init__(self, reason=None, requeue=False):
  76. self.reason = reason
  77. self.requeue = requeue
  78. super(Reject, self).__init__(reason, requeue)
  79. def __repr__(self):
  80. return 'reject requeue=%s: %s' % (self.requeue, self.reason)
  81. class WorkerTerminate(SystemExit):
  82. """Signals that the worker should terminate immediately."""
  83. SystemTerminate = WorkerTerminate # XXX compat
  84. class WorkerShutdown(SystemExit):
  85. """Signals that the worker should perform a warm shutdown."""
  86. class QueueNotFound(KeyError):
  87. """Task routed to a queue not in ``conf.queues``."""
  88. class ImproperlyConfigured(ImportError):
  89. """Celery is somehow improperly configured."""
  90. @python_2_unicode_compatible
  91. class NotRegistered(KeyError, CeleryError):
  92. """The task is not registered."""
  93. def __repr__(self):
  94. return UNREGISTERED_FMT.format(self)
  95. class AlreadyRegistered(CeleryError):
  96. """The task is already registered."""
  97. class TimeoutError(CeleryError):
  98. """The operation timed out."""
  99. class MaxRetriesExceededError(CeleryError):
  100. """The tasks max restart limit has been exceeded."""
  101. class TaskRevokedError(CeleryError):
  102. """The task has been revoked, so no result available."""
  103. class NotConfigured(CeleryWarning):
  104. """Celery has not been configured, as no config module has been found."""
  105. class AlwaysEagerIgnored(CeleryWarning):
  106. """send_task ignores :setting:`task_always_eager` option"""
  107. class InvalidTaskError(CeleryError):
  108. """The task has invalid data or is not properly constructed."""
  109. class IncompleteStream(CeleryError):
  110. """Found the end of a stream of data, but the data is not yet complete."""
  111. class ChordError(CeleryError):
  112. """A task part of the chord raised an exception."""
  113. class CPendingDeprecationWarning(PendingDeprecationWarning):
  114. pass
  115. class CDeprecationWarning(DeprecationWarning):
  116. pass
  117. class FixupWarning(CeleryWarning):
  118. pass
  119. class DuplicateNodenameWarning(CeleryWarning):
  120. """Multiple workers are using the same nodename."""