**注意:会阻塞程序运行, 如果后台运行, 请放置于线程中**

    这个会阻塞程序运行, 如果不是这个目的, 请确保待装饰程序以线程方式运行

    * periods 是正常提供的参数, 如 10s, 则函数每10s 运行一次
    * precision 精度,
        * 如3s, 则 0~3s 内都可以触发运行
        * 如果是0s, 则函数可在  ```sleep check_interval``` 后, 一直运行
    * offset 偏移
        * 如果需要在 3s~6s 内运行, 则可设置 offset 为3, 这样到检测时间后, 会延迟 3s 运行

    example:
    ::

        @dec.threads(1)
        @later(...)
        def fn():
            print('test later')

    定期运行指定函数的装饰器, 如果precision 为0,则函数可一直运行

    :param periods: 函数运行周期 s
    :type periods: ``float``
    :param precision: 函数到运行周期, 可触发运行的容忍范围 s
    :type precision: ``float``
    :param offset: 从运行周期开始, 触发运行向后偏移时间 s
    :type offset: ``float``
    :param check_interval: 检测是否触发的间隔, 用来释放 cpu 资源
    :type check_interval: ``float``
    :param only_run_once: 周期内是否只运行一次
    :type only_run_once: ``bool``
    :return: 返回函数装饰器
    :rtype:

def later(periods=10.0, precision=2.0, offset=0.0, check_interval=0.1, only_run_once=True):
    """
    **注意:会阻塞程序运行, 如果后台运行, 请放置于线程中**

    这个会阻塞程序运行, 如果不是这个目的, 请确保待装饰程序以线程方式运行

    * periods 是正常提供的参数, 如 10s, 则函数每10s 运行一次
    * precision 精度,
        * 如3s, 则 0~3s 内都可以触发运行
        * 如果是0s, 则函数可在  ```sleep check_interval``` 后, 一直运行
    * offset 偏移
        * 如果需要在 3s~6s 内运行, 则可设置 offset 为3, 这样到检测时间后, 会延迟 3s 运行

    example:
    ::

        @dec.threads(1)
        @later(...)
        def fn():
            print('test later')

    定期运行指定函数的装饰器, 如果precision 为0,则函数可一直运行

    :param periods: 函数运行周期 s
    :type periods: ``float``
    :param precision: 函数到运行周期, 可触发运行的容忍范围 s
    :type precision: ``float``
    :param offset: 从运行周期开始, 触发运行向后偏移时间 s
    :type offset: ``float``
    :param check_interval: 检测是否触发的间隔, 用来释放 cpu 资源
    :type check_interval: ``float``
    :param only_run_once: 周期内是否只运行一次
    :type only_run_once: ``bool``
    :return: 返回函数装饰器
    :rtype:
    """

    def dec_fn(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                while True:
                    # 检测时间
                    _st = time.time()

                    # 如果 precision 不为 0, 则触发检查容忍周期
                    _ready = not precision
                    if not _ready:
                        # 当前时间 - 偏移 对周期取余 满足小于精度, 则运行
                        _ready = (_st - offset) % periods <= precision

                    if _ready:
                        # 条件符合, 则运行处理函数
                        fn(*args, **kwargs)
                        # 计算函数运行时间
                        _es = time.time() - _st
                        # 如果要保证只运行一次, 且函数处理时间 小于 精度缓冲时间,
                        # 为了保证只运行一次, 需要额外等待 (精度 - 处理时间)
                        # 如果周期小于精度, 则取两者最小值
                        _extra_max_wait = min(periods, precision)
                        if only_run_once and _es < _extra_max_wait:
                            time.sleep(_extra_max_wait - _es)
                    time.sleep(check_interval)
            except KeyboardInterrupt as ____:
                raise SystemExit(1)
                # except Exception as err:
                #     print('error of later: {}'.format(err))

        return wrapper

    return dec_fn