Skip to main content
Skip table of contents

Writing a Greeter Client in Python

This page presents a step-by-step guide to writing the client-side of our Python Greeter application.

This client creates a proxy to a remote object that implements the Greeter interface and invokes the greet operation on this object.

You can find the complete source code for this example in the ice-demos repository on GitHub.

Compile Slice File with Slice Compiler

The first step when writing a Python application with Ice is to compile its Slice definitions using the Slice to Python compiler (slice2py).

Here we compile the Greeter.ice Slice file we wrote earlier.

This compilation generates a Python package named VisitorCenter, which matches the Slice module name. Inside this package, you’ll find the generated Greeter module corresponding to the Greeter interface defined in Slice. This module provides the APIs that our client code will call, so generating it is an essential first step in the development process.

Client Implementation

The structure of our client is going to look like:

PY
import asyncio
import sys

import Ice

# Slice module VisitorCenter in Greeter.ice maps to Python module VisitorCenter.
import VisitorCenter
...

Before anything else, we need to import a few packages:

  • asyncio To write async code using async/awaitsyntax.

  • sysFor accessing the command line arguments.

  • IceFor accessing the Ice runtime.

  • VisitorCenterThe package generated by slice2py from Greeter.ice.

Then we get to the interesting part: The client logic. This logic can be broken down into four pieces:

1. Create a Communicator

First, we create a Communicator using its constructor:

PY
async def main():
    async with Ice.Communicator(
        sys.argv, eventLoop=asyncio.get_running_loop()) as communicator:

The communicator is the main entry point into the Ice runtime. Its responsibilities include establishing connections to servers, caching these connections, and managing configuration properties. We also need a communicator to create a proxy (see next step).

Our client, like most Ice applications, creates a single communicator.

We define main as an async def function to build an asynchronous application. By passing the current asyncio event loop to Ice.initialize, we ensure that the communicator integrates with this loop for all asynchronous operations.

It is important to always destroy the communicator before exiting the application. This guarantees that network connections are properly closed and other clean-up tasks are performed. In an asynchronous application, the simplest way to achieve this is to use the async with statement, as shown above.

2. Create a Greeter Proxy

Next, we need a way to call on a remote Greeter object. In Ice, this is done with proxies. Proxies are local constructs that represent remote Ice objects and provide functions to call operations on those objects.

We create a Greeter proxy by constructing an instance of the GreeterPrx class generated by the Slice compiler:

PY
greeter = VisitorCenter.GreeterPrx(communicator, "greeter:tcp -h localhost -p 4061")

The constructor accepts our communicator and a “stringified proxy” with the address of the remote Ice object. Here, our stringified proxy says that the target Ice object is named “greeter” and can be reached via tcp on localhost on port 4061.

The name of the interface (Greeter) and the identity of the Ice object (greeter) are independent. The Ice objects hosted in the server could just as easily have identities like santa, bugsBunny, etc.

3. Make an Invocation

The third step is to call greet on the remote Ice object using our proxy and then print the returned greeting:

PY
username = ....
greeting = await greeter.greetAsync(username);
print(greeting);

The greetAsync function does all the heavy lifting for us: the proxy creates a request with the username string, the communicator establishes a connection to localhost:4061, and the request is sent over it. When a response is received, the proxy unmarshals its payload and returns a string (the greeting).

Note that greetAsync returns an Awaitableobject that we await. This allows the event loop thread to do other work while it is waiting for the invocation to complete.

Because the communicator was initialized with an asyncio event loop, the returned Awaitable is an asyncio.Future, which can be awaited within the same event loop.

4. Cleanup

Finally, at the end of our logic, our communicator goes out of scope and is destroyed automatically (because we used the async withstatement), and then our application exits.

Running the Client

After building the client (see the demo’s README for instructions), you can run it with:

BASH
python main.py

This client won’t work unless you’ve also launched a Greeter server.
Writing and running a Greeter server is covered on the next page.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.