替代threading.Timer?

时间:2016-09-12 19:55:54

标签: python python-2.7 timer python-multithreading

我有一个生产者 - 消费者模式队列,它消耗传入的事件并安排在5秒内发送的合格事件。我正在使用threading.Timer() python document来执行此操作,一切正常。

最近,我被要求将预定时间从5秒更改为30分钟,并且threading.Timer()崩溃了我的脚本,因为以前创建了线程对象并且很快就会释放(仅持续5秒),但现在它必须保持活力30分钟。

以下是代码:

 if scheduled_time and out_event:
     threading.Timer(scheduled_time, self.send_out_event, (socket_connection, received_event, out_event,)).start()  # schedule event send out

有人可以对此有所了解吗?我该如何解决这个问题,或者threading.Timer()还有其他选择吗?

1 个答案:

答案 0 :(得分:0)

感谢@dano对第三方模块的评论!根据我的工作要求,我没有在服务器上安装它们。

我没有使用threading.Timer(),而是选择使用基于Redis的延迟队列,我在网上找到了一些有用的资源:A unique Python redis-based queue with delay。它解决了我的问题。

简而言之,作者在redis中创建一个有序集并为其命名,add()会将新数据附加到有序集合中。每次根据epoc-time得分从排序集中弹出最多一个元素时,将弹出保持合格最低分数的元素(不从redis删除

def add(self, received_event, delay_queue_name="delay_queue", delay=config.SECOND_RETRY_DELAY):
    try:
        score = int(time.time()) + delay
        self.__client.zadd(delay_queue_name, score, received_event)
        self.__logger.debug("added {0} to delay queue, delay time:{1}".format(received_event, delay))
    except Exception as e:
        self.__logger.error("error: {0}".format(e))


def pop(self, delay_queue_name="delay_queue"):
    min_score, max_score, element = 0, int(time.time()), None

    try:
        result = self.__client.zrangebyscore(delay_queue_name, min_score, max_score, start=0, num=1, withscores=False)
    except Exception as e:
        self.__logger.error("failed query from redis:{0}".format(e))
        return None

    if result and len(result) == 1:
        element = result[0]
        self.__logger.debug("poped {0} from delay queue".format(element))
    else:
        self.__logger.debug("no qualified element")
    return element

def remove(self, element, delay_queue_name="delay_queue"):
    self.__client.zrem(delay_queue_name, element)

self.__client是Redis客户端实例redis.StrictRedis(host=rhost,port=rport, db=rindex)

与我的在线资源之间的区别在于我切换了zadd()个参数。 scoredata的顺序已切换。以下是 zadd()

的文档

这是python redis doc:

# SORTED SET COMMANDS
def zadd(self, name, *args, **kwargs):
    """
    Set any number of score, element-name pairs to the key ``name``. Pairs
    can be specified in two ways:

    As *args, in the form of: score1, name1, score2, name2, ...
    or as **kwargs, in the form of: name1=score1, name2=score2, ...

    The following example would add four values to the 'my-key' key:
    redis.zadd('my-key', 1.1, 'name1', 2.2, 'name2', name3=3.3, name4=4.4)
    """
    pieces = []
    if args:
        if len(args) % 2 != 0:
            raise RedisError("ZADD requires an equal number of "
                             "values and scores")
        pieces.extend(args)
    for pair in iteritems(kwargs):
        pieces.append(pair[1])
        pieces.append(pair[0])
    return self.execute_command('ZADD', name, *pieces)