Skip to content

Commit

Permalink
0.9.60 新增 timeout_decorator 装饰器
Browse files Browse the repository at this point in the history
  • Loading branch information
zengbin93 committed Oct 14, 2024
1 parent 05dc982 commit 32e469e
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
1 change: 1 addition & 0 deletions czsc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
ExitsOptimize,
)
from czsc.utils import (
timeout_decorator,
mac_address,
overlap,
to_arrow,
Expand Down
30 changes: 30 additions & 0 deletions czsc/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# coding: utf-8
import os
import functools
import pandas as pd
from typing import List, Union
from loguru import logger

from . import qywx
from . import ta
Expand Down Expand Up @@ -226,3 +228,31 @@ def to_arrow(df: pd.DataFrame):
with pa.ipc.new_file(sink, table.schema) as writer:
writer.write_table(table)
return sink.getvalue()


def timeout_decorator(timeout):
"""超时装饰器
:param timeout: int, 超时时间,单位秒
"""

def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
from concurrent.futures import ThreadPoolExecutor, TimeoutError

with ThreadPoolExecutor() as executor:
future = executor.submit(func, *args, **kwargs)
try:
result = future.result(timeout=timeout)
return result
except TimeoutError:
# print(f"{func.__name__} timed out after {timeout} seconds")
logger.warning(
f"{func.__name__} timed out after {timeout} seconds;" f"args: {args}; kwargs: {kwargs}"
)
raise ValueError(f"{func.__name__} timed out after {timeout} seconds")

return wrapper

return decorator
21 changes: 21 additions & 0 deletions test/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
"""
import sys
import pytest
import time
import pandas as pd
import numpy as np
from czsc import utils
from czsc.utils import timeout_decorator


def test_x_round():
Expand Down Expand Up @@ -344,3 +346,22 @@ def test_overlap():

# 验证结果
assert result["col_overlap"].tolist() == [1, 2, 1, 2, 1]


def test_timeout_decorator_success():
@timeout_decorator(2)
def fast_function():
time.sleep(1)
return "Completed"

assert fast_function() == "Completed"


def test_timeout_decorator_timeout():
@timeout_decorator(1)
def slow_function():
time.sleep(2)
return "Completed"

with pytest.raises(ValueError, match="timed out after 1 seconds"):
slow_function()

0 comments on commit 32e469e

Please sign in to comment.