python3 - функция декоратора: переменная, на которую ссылаются перед присваиванием - PullRequest
0 голосов
/ 12 октября 2018

Я работаю над микросервисом gRPC .

Поскольку каждый метод должен сначала загрузить строку JSON из аргумента request, а затем в конце вывести ее снова, я хочуиспользовать декоратор в методах класса, чтобы сам метод, кроме 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: локальная переменная 'request', на которую ссылается перед присваиванием

Ошибка возникает из-за этого: (Например, реальная вещь немного сложнее)

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) вместо этого.Но затем я получаю эту ошибку:

, если запрос ["source_machine"] и запрос ["dest_machine"]: TypeError:

Объект 'JsonContextRequest'не подписывается

В качестве аргумента request вводится объект типа <class 'SetupService_pb2.JsonContextRequest'> Строка JSON в запросе будет доступна через атрибут request.context.

Я думаю, что проблема связана с тем, как вызывается функция декоратора.Я полагаю, что если бы он был вызван во время выполнения метода класса, переменной запроса уже должен был быть присвоен объект запроса.

Но, возможно, я полностью здесь не так.Так как бы вы решили это?

1 Ответ

0 голосов
/ 12 октября 2018

В вашем коде есть несколько ошибок:

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
...