Merge pull request #85 from jtattermusch/python_helloworld
"Hello World" for Python
This commit is contained in:
commit
5411b0d08a
|
|
@ -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