We have scheduled some automated tasks that run regularly. They work well under normal circumstances. However, we realized that during Chinese public holidays, we don’t need to execute some of these tasks.
To handle this, we use the tool 中国节假日 (chinesecalendar) to detect whether the current date is a working day in China. By combining it with a Python decorator, we can easily control whether a function should run based on the calendar.
Below is the decorator implementation that checks if today is a working day before running the decorated function.
import datetime
import logging
from functools import wraps
from chinese_calendar import is_workday
def chinese_workday_check(func):
@wraps(func)
def wrapper(*args, **kwargs):
today = datetime.date.today()
if is_workday(today):
logging.info(f"Today is a workday: {today}. Executing function '{func.__name__}'.")
return func(*args, **kwargs)
else:
logging.info(f"Today is not a workday: {today}. Function '{func.__name__}' will not be executed.")
return None
return wrapper
@chinese_workday_check
def my_function():
print("Function is executed.")
@chinese_workday_check
is a decorator. When applied to a function (like my_function
), it wraps the function’s behavior.wrapper()
inside the decorator.is_workday(today)
from the chinesecalendar
library.
*args
In Python, *args
allows a function to accept any number of positional arguments.
For example:
def example(*args):
print(args)
for arg in args:
print("Argument:", arg)
example(1, 2, 3, "hello")
Output:
(1, 2, 3, 'hello')
Argument: 1
Argument: 2
Argument: 3
Argument: hello
args
is a tuple containing all positional arguments passed to the function.*args
ensures the wrapper can forward all positional arguments to the original function, keeping its signature flexible.**kwargs
Similarly, **kwargs
allows a function to accept any number of keyword arguments.
Example:
def example(**kwargs):
print(kwargs)
for key, value in kwargs.items():
print(f"{key} = {value}")
example(name="Alice", age=25, city="Chengdu")
Output:
{'name': 'Alice', 'age': 25, 'city': 'Chengdu'}
name = Alice
age = 25
city = Chengdu
kwargs
is a dictionary (dict
) containing all keyword arguments.**kwargs
ensures all keyword arguments are correctly passed through to the decorated function, so the decorator does not interfere with the original function’s flexibility.*args
and **kwargs
Decorators often use both *args
and **kwargs
because:
Example of a decorated function with parameters:
@chinese_workday_check
def generate_report(department, date=None):
print(f"Generating report for {department} on {date or datetime.date.today()}")
generate_report("Finance")
This will:
generate_report()
with all its original arguments if it is.Concept | Description |
---|---|
Decorator | A wrapper that modifies or enhances another function’s behavior. |
*args |
Collects all positional arguments into a tuple. |
**kwargs |
Collects all keyword arguments into a dictionary. |
Use Case | Skipping task execution on non-workdays based on the Chinese calendar. |
(Edit with ChatGPT)