【问题标题】:python gRPC requiring a context argumentpython gRPC需要一个上下文参数
【发布时间】:2017-08-30 03:08:34
【问题描述】:

我刚刚开始使用 gRPC,并在阅读入门指南后尝试实现一个简单的 python 服务。但是当我调用我的客户端调用时,python 要求提供一个上下文参数。为什么我的代码在示例中不需要时需要提供上下文对象?

附:我开始尝试创建自己的具体上下文子类,但不确定应该如何实现。我已经添加了我的开始,但如果可能的话,我真的很感激一个例子来工作

谢谢!

原型

syntax = "proto2";

package parsefile;

service ParseFile {
  rpc SendFile (File) returns (Empty) {}
}

message File {

  message MetaData {
    optional string file_name = 1;
    optional string file_path = 2 [default = '.'];
    optional string mime_type = 3 [default = 'application/pdf'];
  }

  message Source {
    optional string title = 1;
    optional int32 id = 2;
  }

  optional MetaData document = 1;
  optional Source supplier = 2;
}

message Empty {
}

服务器

from concurrent import futures
import time

import grpc

import parsefile_pb2_grpc
import parsefile_pb2

_ONE_DAY_IN_SECONDS = 60 * 60 * 24

class ParseFileServicer(parsefile_pb2_grpc.ParseFileServicer):

    def SendFile(self, request, context):
        supplier = request.supplier.title
        file_name = request.document.file_name
        print('Received {} from {}'.format(file_name, supplier))
        return parsefile_pb2.Empty()

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=2))
    parsefile_pb2_grpc.add_ParseFileServicer_to_server(
        ParseFileServicer, server)
    server.add_insecure_port('[::]:50051')
    server.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == '__main__':
    serve()

客户

import grpc

import parsefile_pb2_grpc
import parsefile_pb2

def get_file_info():
    return parsefile_pb2.File(
        document = parsefile_pb2.File.MetaData(
            file_name = 'example.txt'
        ),
        supplier = parsefile_pb2.File.Source(
            title = 'Example Supplier'
        )
    )

def run():
    channel = grpc.insecure_channel('localhost:50051')
    stub = parsefile_pb2_grpc.ParseFileStub(channel)
    context = RequestContext()
    print('object created')
    response = stub.SendFile(get_file_info())
    print('File info sent to server')

if __name__ == '__main__':
    run()

错误追踪

Traceback (most recent call last):   File "parse_client.py", line 60, in <module>
    run()   File "parse_client.py", line 56, in run
    response = stub.SendFile(get_file_info(), 2)   File "/Users/davidbowe/.virtualenvs/post/lib/python3.6/site-packages/grpc/_channel.py", line 507, in __call__
    return _end_unary_response_blocking(state, call, False, deadline)   File "/Users/davidbowe/.virtualenvs/post/lib/python3.6/site-packages/grpc/_channel.py", line 455, in _end_unary_response_bl ocking
    raise _Rendezvous(state, None, None, deadline) grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with (StatusCode.UNKNOWN, Exception calling application: SendF ile() missing 1 required positional argument: 'context')>

【问题讨论】:

  • 你能提供你看到的确切错误吗?
  • parsefile_pb2_grpc.add_ParseFileServicer_to_server(ParseFileServicer, server) 我认为你传递 ParseFileServicer 类对象而不是 ParseFileServicer 实例是错误的。考虑将其更改为 parsefile_pb2_grpc.add_ParseFileServicer_to_server(ParseFileServicer(), server)?
  • 不敢相信就是这样!非常感谢@NathanielManistaAtGoogle。我已经更新了问题,以便为任何感兴趣的人显示错误跟踪。
  • 另外,你能告诉我上下文子类的示例实现吗?我会继续浏览文档,但最好使用模板。谢谢!
  • 我无法为您指出这样的示例,因为ServicerContext 接口旨在由 gRPC Python 实现,而不是由应用程序实现。如果一个应用程序认为它应该实现ServicerContext 接口,或者认为它必须这样做,那么我们根本没有想到的非常奇怪的事情正在发生。

标签: python grpc


【解决方案1】:

在您的服务器代码中,您缺少用于实例化服务对象的括号。你写的……

parsefile_pb2_grpc.add_ParseFileServicer_to_server(ParseFileServicer, server)

应该是:

parsefile_pb2_grpc.add_ParseFileServicer_to_server(ParseFileServicer(), server)

【讨论】:

  • 我知道这个答案已经有一年了,但你让我省了很多麻烦!谢谢!
  • 我知道这个答案已经有两年了,但你让我免于浪费更多时间(current_waste:3 小时)
【解决方案2】:

context参数不用创建,由grpc自动创建。

【讨论】:

  • 我正在尝试在 grpc 服务端进行单元测试,我想使用模拟上下文。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2021-12-30
  • 2011-10-07
  • 2018-12-12
  • 1970-01-01
  • 2019-01-11
  • 2019-11-25
  • 2017-12-11
  • 2020-03-09
相关资源
最近更新 更多