I have python decorator and I need pass contextVariable inside my decorator or as argument request_id in function
Step 1: Declare contextVariables and methods
_correlation_id_ctx_var: ContextVar[str] = ContextVar(CORRELATION_ID_CTX_KEY, default=None)
_request_id_ctx_var: ContextVar[str] = ContextVar(REQUEST_ID_CTX_KEY, default=None)
def get_correlation_id() -> str:
return _correlation_id_ctx_var.get()
def get_request_id() -> str:
return _request_id_ctx_var.get()
Step 2: The context Variable I declare inside middleware (use FastApi)
@app.middleware("http")
async def log_request(request: Request, call_next):
correlation_id = _correlation_id_ctx_var.set(request.headers.get('X-Correlation-ID', str(uuid4())))
request_id = _request_id_ctx_var.set(str(uuid4()))
Step3: I try to pass contextVariable to decorator - it always None Try to pass as argument in function itself - it always None
What it the problem?
Why contextVars accessible in function body only and not in decorator or argument function?
Is there any solutions to have access to contextVar before function body?
@app.get('/test')
@decorator(request_id=get_request_id())
def test_purpose(request_id=get_request_id()):
print('get_correlation_id() start', get_request_id())
return 'ok'
Decorator:
def decorator(request_id=None, *args, **kwargs):
def logger(func, request_id=None, *args, **kwargs):
@wraps(func, *args, **kwargs)
def wrapper(*args, **kwargs):
try:
res = func()
print()
return res
except Exception:
pass
return wrapper
return logger
@decorator(request_id=get_request_id())<- this line is executed when your module is imported. Which means your getter function is called only once, when the module is imported, not each time your decorated function is called.To fix it, just pass the getter function, not its result, to the decorator, and make the call inside the wrapper function, inside the decorator. (For that, just leave the parentheses out):