我正在开发gRPC微服务。
因为每个方法都必须首先从request
参数中加载一个JSON字符串,然后最后再次将其转储,所以我想在类的方法上使用装饰器,以便该方法本身除了return
仅包含下面的... more stuff to do ...
:
class VPPSetupService(SetupService_pb2_grpc.VPPSetupServiceServicer):
...
def method(self, request, context):
request = json.loads(request.context)
request = request["request"]
header = request["headers"]
... more stuff to do ...
response = json.dumps(response)
return SetupService_pb2.JsonContextResponse(context=response)
所以我写了一个装饰器函数。 但是,我找不到此错误的解决方案:
request = json.loads(request.context)
UnboundLocalError:分配前已引用本地变量“请求”
错误是由此产生的(例如,真实的东西要复杂一些)
from functools import wraps
def json_and_error(func):
@wraps(func)
def args_wrapper(*args, **kwargs): # Problem: This
request = json.loads(request.context) <<# variable is referenced
request = request["request"] # before assignment
header = request["headers"]
func(*args, **kwargs)
return func(*args, **kwargs)
return args_wrapper
class VPPSetupService(SetupService_pb2_grpc.VPPSetupServiceServicer):
...
@json_and_error
def method(self, request, context):
... more stuff to do ...
return SetupService_pb2.JsonContextResponse(context=response)
我尝试使用request = json.loads(args[1].context)
代替。但是然后我得到这个错误:
如果request [“ source_machine”]和request [“ dest_machine”]:TypeError:
“ JsonContextRequest”对象不可下标
以request
参数形式输入的输入是<class 'SetupService_pb2.JsonContextRequest'>
类型的对象。可以通过request.context
属性访问请求中的JSON字符串。
我在想这个问题与装饰器函数的调用方式有关。我想如果在类方法的运行时调用了该变量请求,则应该已经为其分配了请求对象。
但是,也许我在这里完全错了。那你怎么解决呢?
答案 0 :(得分:1)
您的代码中几乎没有错误:
def args_wrapper(*args, **kwargs):
request = json.loads(request.context)
您正在使用request.context
,而request
变量未定义(只有在执行json.loads(request.context)
之后才定义)。您尝试使用request = json.loads(args[1].context)
对其进行了修复,但包装功能中包含JsonContextRequest object is not subscriptable
。仔细看这行:
return func(*args, **kwargs)
您的装饰器返回以相同的参数调用的包装函数,因此不会使用此代码结果,也不会将请求和标头传递给包装函数:
request = json.loads(request.context)
request = request["request"]
header = request["headers"]
您也不应该调用包装函数:
func(*args, **kwargs)
我猜你想做这样的事情:
def json_and_error(func):
def args_wrapper(this, request):
context = request.context
request = json.loads(context)
request = request["request"]
return func(this, request, context)
return args_wrapper