parent
68290c2b24
commit
7dfd4abba5
9 changed files with 440 additions and 0 deletions
@ -0,0 +1 @@ |
||||
*.pyc |
@ -0,0 +1,111 @@ |
||||
# gRPC Python Hello World Tutorial |
||||
|
||||
### Install gRPC |
||||
Make sure you have built gRPC Python from source on your system. Follow the instructions here: |
||||
[https://github.com/grpc/grpc/blob/master/src/python/README.md](https://github.com/grpc/grpc/blob/master/src/python/README.md). |
||||
|
||||
This gives you a python virtual environment with installed gRPC Python |
||||
in GRPC_ROOT/python2.7_virtual_environment. GRPC_ROOT is the path to which you |
||||
have cloned the [gRPC git repo](https://github.com/grpc/grpc). |
||||
|
||||
### Get the tutorial source code |
||||
|
||||
The example code for this and our other examples live in the `grpc-common` |
||||
GitHub repository. Clone this repository to your local machine by running the |
||||
following command: |
||||
|
||||
|
||||
```sh |
||||
$ git clone https://github.com/google/grpc-common.git |
||||
``` |
||||
|
||||
Change your current directory to grpc-common/python/helloworld |
||||
|
||||
```sh |
||||
$ cd grpc-common/python/helloworld/ |
||||
``` |
||||
|
||||
### Defining a service |
||||
|
||||
The first step in creating our example is to define a *service*: an RPC |
||||
service specifies the methods that can be called remotely with their parameters |
||||
and return types. As you saw in the |
||||
[overview](#protocolbuffers) above, gRPC does this using [protocol |
||||
buffers](https://developers.google.com/protocol-buffers/docs/overview). We |
||||
use the protocol buffers interface definition language (IDL) to define our |
||||
service methods, and define the parameters and return |
||||
types as protocol buffer message types. Both the client and the |
||||
server use interface code generated from the service definition. |
||||
|
||||
Here's our example service definition, defined using protocol buffers IDL in |
||||
[helloworld.proto](https://github.com/grpc/grpc-common/blob/master/python/helloworld/helloworld.proto). The `Greeting` |
||||
service has one method, `hello`, that lets the server receive a single |
||||
`HelloRequest` |
||||
message from the remote client containing the user's name, then send back |
||||
a greeting in a single `HelloReply`. This is the simplest type of RPC you |
||||
can specify in gRPC. |
||||
|
||||
``` |
||||
syntax = "proto2"; |
||||
|
||||
// The greeting service definition. |
||||
service Greeter { |
||||
// Sends a greeting |
||||
rpc SayHello (HelloRequest) returns (HelloReply) {} |
||||
} |
||||
|
||||
// The request message containing the user's name. |
||||
message HelloRequest { |
||||
optional string name = 1; |
||||
} |
||||
|
||||
// The response message containing the greetings |
||||
message HelloReply { |
||||
optional string message = 1; |
||||
} |
||||
|
||||
``` |
||||
|
||||
<a name="generating"></a> |
||||
### Generating gRPC code |
||||
|
||||
Once we've defined our service, we use the protocol buffer compiler |
||||
`protoc` to generate the special client and server code we need to create |
||||
our application. The generated code contains both stub code for clients to |
||||
use and an abstract interface for servers to implement, both with the method |
||||
defined in our `Greeting` service. |
||||
|
||||
To generate the client and server side interfaces: |
||||
|
||||
```sh |
||||
$ ./run_codegen.sh |
||||
``` |
||||
Which internally invokes the proto-compiler as: |
||||
|
||||
```sh |
||||
$ protoc -I . --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_python_plugin` helloworld.proto |
||||
``` |
||||
|
||||
Optionally, you can just skip the code generation step as the generated python module has already |
||||
been generated for you (helloworld_pb2.py). |
||||
|
||||
### The client |
||||
|
||||
Client-side code can be found in [greeter_client.py](https://github.com/grpc/grpc-common/blob/master/python/helloworld/greeter_client.py). |
||||
|
||||
You can run the client using: |
||||
|
||||
```sh |
||||
$ ./run_client.sh |
||||
``` |
||||
|
||||
|
||||
### The server |
||||
|
||||
Server side code can be found in [greeter_server.py](https://github.com/grpc/grpc-common/blob/master/python/helloworld/greeter_server.py). |
||||
|
||||
You can run the server using: |
||||
|
||||
```sh |
||||
$ ./run_server.sh |
||||
``` |
@ -0,0 +1,44 @@ |
||||
# Copyright 2015, Google Inc. |
||||
# All rights reserved. |
||||
# |
||||
# Redistribution and use in source and binary forms, with or without |
||||
# modification, are permitted provided that the following conditions are |
||||
# met: |
||||
# |
||||
# * Redistributions of source code must retain the above copyright |
||||
# notice, this list of conditions and the following disclaimer. |
||||
# * Redistributions in binary form must reproduce the above |
||||
# copyright notice, this list of conditions and the following disclaimer |
||||
# in the documentation and/or other materials provided with the |
||||
# distribution. |
||||
# * Neither the name of Google Inc. nor the names of its |
||||
# contributors may be used to endorse or promote products derived from |
||||
# this software without specific prior written permission. |
||||
# |
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
"""The Python implementation of the GRPC helloworld.Greeter client.""" |
||||
|
||||
import helloworld_pb2 |
||||
|
||||
_TIMEOUT_SECONDS = 10 |
||||
|
||||
|
||||
def run(): |
||||
with helloworld_pb2.early_adopter_create_Greeter_stub('localhost', 50051) as stub: |
||||
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'), _TIMEOUT_SECONDS) |
||||
print "Greeter client received: " + response.message |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
run() |
@ -0,0 +1,56 @@ |
||||
# Copyright 2015, Google Inc. |
||||
# All rights reserved. |
||||
# |
||||
# Redistribution and use in source and binary forms, with or without |
||||
# modification, are permitted provided that the following conditions are |
||||
# met: |
||||
# |
||||
# * Redistributions of source code must retain the above copyright |
||||
# notice, this list of conditions and the following disclaimer. |
||||
# * Redistributions in binary form must reproduce the above |
||||
# copyright notice, this list of conditions and the following disclaimer |
||||
# in the documentation and/or other materials provided with the |
||||
# distribution. |
||||
# * Neither the name of Google Inc. nor the names of its |
||||
# contributors may be used to endorse or promote products derived from |
||||
# this software without specific prior written permission. |
||||
# |
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
"""The Python implementation of the GRPC helloworld.Greeter server.""" |
||||
|
||||
import time |
||||
|
||||
import helloworld_pb2 |
||||
|
||||
_ONE_DAY_IN_SECONDS = 60 * 60 * 24 |
||||
|
||||
|
||||
class Greeter(helloworld_pb2.EarlyAdopterGreeterServicer): |
||||
|
||||
def SayHello(self, request, context): |
||||
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) |
||||
|
||||
|
||||
def serve(): |
||||
server = helloworld_pb2.early_adopter_create_Greeter_server( |
||||
Greeter(), 50051, None, None) |
||||
server.start() |
||||
try: |
||||
while True: |
||||
time.sleep(_ONE_DAY_IN_SECONDS) |
||||
except KeyboardInterrupt: |
||||
server.stop() |
||||
|
||||
if __name__ == '__main__': |
||||
serve() |
@ -0,0 +1,49 @@ |
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
syntax = "proto2"; |
||||
|
||||
//TODO: see https://github.com/grpc/grpc/issues/814 |
||||
//package examples; |
||||
|
||||
// The greeting service definition. |
||||
service Greeter { |
||||
// Sends a greeting |
||||
rpc SayHello (HelloRequest) returns (HelloReply) {} |
||||
} |
||||
|
||||
// The request message containing the user's name. |
||||
message HelloRequest { |
||||
optional string name = 1; |
||||
} |
||||
|
||||
// The response message containing the greetings |
||||
message HelloReply { |
||||
optional string message = 1; |
||||
} |
@ -0,0 +1,158 @@ |
||||
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
# source: helloworld.proto |
||||
|
||||
import sys |
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) |
||||
from google.protobuf import descriptor as _descriptor |
||||
from google.protobuf import message as _message |
||||
from google.protobuf import reflection as _reflection |
||||
from google.protobuf import symbol_database as _symbol_database |
||||
from google.protobuf import descriptor_pb2 |
||||
# @@protoc_insertion_point(imports) |
||||
|
||||
_sym_db = _symbol_database.Default() |
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor( |
||||
name='helloworld.proto', |
||||
package='', |
||||
serialized_pb=_b('\n\x10helloworld.proto\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t23\n\x07Greeter\x12(\n\x08SayHello\x12\r.HelloRequest\x1a\x0b.HelloReply\"\x00') |
||||
) |
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR) |
||||
|
||||
|
||||
|
||||
|
||||
_HELLOREQUEST = _descriptor.Descriptor( |
||||
name='HelloRequest', |
||||
full_name='HelloRequest', |
||||
filename=None, |
||||
file=DESCRIPTOR, |
||||
containing_type=None, |
||||
fields=[ |
||||
_descriptor.FieldDescriptor( |
||||
name='name', full_name='HelloRequest.name', index=0, |
||||
number=1, type=9, cpp_type=9, label=1, |
||||
has_default_value=False, default_value=_b("").decode('utf-8'), |
||||
message_type=None, enum_type=None, containing_type=None, |
||||
is_extension=False, extension_scope=None, |
||||
options=None), |
||||
], |
||||
extensions=[ |
||||
], |
||||
nested_types=[], |
||||
enum_types=[ |
||||
], |
||||
options=None, |
||||
is_extendable=False, |
||||
extension_ranges=[], |
||||
oneofs=[ |
||||
], |
||||
serialized_start=20, |
||||
serialized_end=48, |
||||
) |
||||
|
||||
|
||||
_HELLOREPLY = _descriptor.Descriptor( |
||||
name='HelloReply', |
||||
full_name='HelloReply', |
||||
filename=None, |
||||
file=DESCRIPTOR, |
||||
containing_type=None, |
||||
fields=[ |
||||
_descriptor.FieldDescriptor( |
||||
name='message', full_name='HelloReply.message', index=0, |
||||
number=1, type=9, cpp_type=9, label=1, |
||||
has_default_value=False, default_value=_b("").decode('utf-8'), |
||||
message_type=None, enum_type=None, containing_type=None, |
||||
is_extension=False, extension_scope=None, |
||||
options=None), |
||||
], |
||||
extensions=[ |
||||
], |
||||
nested_types=[], |
||||
enum_types=[ |
||||
], |
||||
options=None, |
||||
is_extendable=False, |
||||
extension_ranges=[], |
||||
oneofs=[ |
||||
], |
||||
serialized_start=50, |
||||
serialized_end=79, |
||||
) |
||||
|
||||
DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST |
||||
DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY |
||||
|
||||
HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( |
||||
DESCRIPTOR = _HELLOREQUEST, |
||||
__module__ = 'helloworld_pb2' |
||||
# @@protoc_insertion_point(class_scope:HelloRequest) |
||||
)) |
||||
_sym_db.RegisterMessage(HelloRequest) |
||||
|
||||
HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( |
||||
DESCRIPTOR = _HELLOREPLY, |
||||
__module__ = 'helloworld_pb2' |
||||
# @@protoc_insertion_point(class_scope:HelloReply) |
||||
)) |
||||
_sym_db.RegisterMessage(HelloReply) |
||||
|
||||
|
||||
import abc |
||||
from grpc._adapter import fore |
||||
from grpc._adapter import rear |
||||
from grpc.framework.assembly import implementations |
||||
from grpc.framework.assembly import utilities |
||||
class EarlyAdopterGreeterServicer(object): |
||||
"""<fill me in later!>""" |
||||
__metaclass__ = abc.ABCMeta |
||||
@abc.abstractmethod |
||||
def SayHello(self, request): |
||||
raise NotImplementedError() |
||||
class EarlyAdopterGreeterServer(object): |
||||
"""<fill me in later!>""" |
||||
__metaclass__ = abc.ABCMeta |
||||
@abc.abstractmethod |
||||
def start(self): |
||||
raise NotImplementedError() |
||||
@abc.abstractmethod |
||||
def stop(self): |
||||
raise NotImplementedError() |
||||
class EarlyAdopterGreeterStub(object): |
||||
"""<fill me in later!>""" |
||||
__metaclass__ = abc.ABCMeta |
||||
@abc.abstractmethod |
||||
def SayHello(self, request): |
||||
raise NotImplementedError() |
||||
SayHello.async = None |
||||
def early_adopter_create_Greeter_server(servicer, port, root_certificates, key_chain_pairs): |
||||
method_implementations = { |
||||
"SayHello": utilities.unary_unary_inline(servicer.SayHello), |
||||
} |
||||
import helloworld_pb2 |
||||
request_deserializers = { |
||||
"SayHello": helloworld_pb2.HelloRequest.FromString, |
||||
} |
||||
response_serializers = { |
||||
"SayHello": lambda x: x.SerializeToString(), |
||||
} |
||||
link = fore.activated_fore_link(port, request_deserializers, response_serializers, root_certificates, key_chain_pairs) |
||||
return implementations.assemble_service(method_implementations, link) |
||||
def early_adopter_create_Greeter_stub(host, port): |
||||
method_implementations = { |
||||
"SayHello": utilities.unary_unary_inline(None), |
||||
} |
||||
import helloworld_pb2 |
||||
response_deserializers = { |
||||
"SayHello": helloworld_pb2.HelloReply.FromString, |
||||
} |
||||
request_serializers = { |
||||
"SayHello": lambda x: x.SerializeToString(), |
||||
} |
||||
link = rear.activated_rear_link(host, port, request_serializers, response_deserializers) |
||||
return implementations.assemble_dynamic_inline_stub(method_implementations, link) |
||||
# @@protoc_insertion_point(module_scope) |
@ -0,0 +1,8 @@ |
||||
#!/bin/bash |
||||
|
||||
# This is where you have cloned out the https://github.com/grpc/grpc repository |
||||
# And built gRPC Python. |
||||
# ADJUST THIS PATH TO WHERE YOUR ACTUAL LOCATION IS |
||||
GRPC_ROOT=~/github/grpc |
||||
|
||||
$GRPC_ROOT/python2.7_virtual_environment/bin/python greeter_client.py |
@ -0,0 +1,4 @@ |
||||
#!/bin/bash |
||||
|
||||
# Runs the protoc with gRPC plugin to generate protocol messages and gRPC stubs. |
||||
protoc -I . --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_python_plugin` helloworld.proto |
@ -0,0 +1,9 @@ |
||||
#!/bin/bash |
||||
|
||||
# This is where you have cloned out the https://github.com/grpc/grpc repository |
||||
# And built gRPC Python. |
||||
# ADJUST THIS PATH TO WHERE YOUR ACTUAL LOCATION IS |
||||
GRPC_ROOT=~/github/grpc |
||||
|
||||
$GRPC_ROOT/python2.7_virtual_environment/bin/python greeter_server.py |
||||
|
Loading…
Reference in new issue