【问题标题】:Signal alarm does not raise error信号报警不报错
【发布时间】:2017-12-28 18:06:26
【问题描述】:

在下面的代码中,我正在尝试创建一个类“TimedExecutor”,如果超过某个时间限制,它将停止执行传递给其方法“execute”的函数(bar)。但是,即使显示错误消息,程序执行也不会停止。

注意:我们不能对函数bar()进行任何更改,因为它是由外部模块提供的。

import signal
import time

class MyError(Exception):
  """Base error"""

class MyInheritedError(MyError):
  """Class to inherit from base error"""


class TimeoutListener(object):
  def __init__(self, timeout_seconds, error_message="Timeout executing."):
    self.timeout_seconds = timeout_seconds
    self.error_message = error_message
    self.alarm = None

  def __enter__(self):
    signal.signal(signal.SIGALRM, self._handle_timeout)
    signal.alarm(self.timeout_seconds)

  def __exit__(self, listener_type, value, traceback):
    # Disable the alarm.
    if self.alarm:
      self.alarm = None
    else:
      signal.alarm(0)

  def _handle_timeout(self, signum, frame):
    print("Got the signum %s with frame: %s" % (signum, frame))
    raise MyInheritedError(self.error_message + "aditya")


class TimedExecutor(object):
  @staticmethod
  def execute(timeout_secs, functor, *args, **kwargs):
    msg = "Timeout executing method - %s." % functor.__name__
    timeout_signal = TimeoutListener(timeout_secs, error_message=msg)
    try:
      with timeout_signal:
        output = functor(*args, **kwargs)
    except MyInheritedError as ex:
      print("%s did not complete in %s: %s."
            % (functor.__name__, timeout_secs, repr(ex)))
      raise
    return output


def bar():
  for _ in range(5):
    try:
      time.sleep(1)
      print("SLEEPING")
    except MyInheritedError as ex:
      print ex


ob = TimedExecutor.execute(2, bar)

【问题讨论】:

    标签: python python-2.7 signals


    【解决方案1】:

    您的函子正在吞噬您打算致命的异常。

    这是bar() 在其循环之一中的except 子句打印然后丢弃TimeoutListener 上下文管理器引发的错误。然后循环继续。

    bar() 可能不知道您的TimedExecutor 可能引发的异常。相反,调用.execute()bar() 的调用者应该意识到这一点:

    from aditya.utils import TimedExecutor, TimeoutException
    
    ...
    
    try:
      TimedExecutor.execute(2, bar)
    except TimeoutException:
      print("Timed out executing bar")
    

    【讨论】:

    • 这个解决方案似乎也不起作用。你能提供一个工作代码吗?
    • 解决方案只是从bar() 中删除try/except 块。我介绍的是伪代码重构。
    • 不行,bar() 函数不能更改,它来自另一个模块。我需要设计一个处理执行超时的代码。
    • 那你能不能把TimedExecutorTimeoutListener改成抛出bar()不知道的异常?那会产生同样的效果。
    • 是的,我们可以这样做,但是如果bar() 使用Exception 怎么办?所有其他错误类都继承自异常
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多