无法访问decorator中的contextVariables



我有python装饰器,我需要将contextVariable作为函数中的参数request_id传递到我的装饰器中

步骤1:声明contextVariables和方法

_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()

步骤2:我在中间件内部声明的上下文变量(使用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()))

步骤3:我尝试将contextVariable传递给decorator-它总是None尝试在函数本身中作为参数传递-它总是None

这是什么问题?

为什么contextVars只能在函数体中访问,而不能在decorator或argument函数中访问?

有什么解决方案可以在函数体之前访问contextVar吗?

@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'

装饰师:

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())<-这一行是在导入模块时执行的。这意味着在导入模块时,getter函数只被调用一次,而不是每次调用装饰函数。

要修复它,只需将getter函数(而不是其结果(传递给decorator,然后在包装器函数内部,在decorator内部进行调用。(为此,只需省略括号(:


def decorator(request_id_getter=None, *d_args, **d_kw): 
def logger(func):  # other arguments than the first positional arg here are not used at all. 
@wraps(func, *d_args, **d_kw)
def wrapper(*args, **kwargs):
request_id = request_id_getter()  # and here the value is retrieved when the function is actually called
try:
res = func()
print()
return res
except Exception:
pass
return wrapper
return logger
@app.get('/test')
@decorator(request_id=get_request_id)  # <- here is the change - do not _call_ the function!
def test_purpose(request_id=get_request_id()):
print('get_correlation_id() start', get_request_id())
return 'ok'

最新更新