Skip to main content

pyease-grpc

Lint Release PyPI version Python version GitHub License Downloads

Easy to use gRPC-web client in python

Installation

Install the package using pip or uv:

$ pip install pyease-grpc
$ uv pip install pyease-grpc

Development

From a clone of this repository, create a virtual environment and install the package with dev tools:

$ uv sync --all-groups

Lint and format (same as CI) with uv run ruff check pyease_grpc and uv run ruff format --check pyease_grpc. Apply formatting with uv run ruff format pyease_grpc. Run the CLI with uv run pyease-grpc --version. Build wheels with uv build.

Run the following to check if the published package has been installed correctly:

$ pyease-grpc --version

Tutorial

Before you start, you need to have a basic understanding of how gRPC works.

This package provides a requests like interface to make calls to native gRPC and gRPC-Web servers.

Example Server

An example server and client can be found in the example folder.

> cd example
> docker compose up

It uses two ports:

  • Native gRPC server: localhost:50050
  • gRPC-Web server using envoy: http://localhost:8080

You can test the native serve with the client:

$ python example/server/client.py
Calling SayHello:
reply: "Hello, world!"

Calling LotsOfReplies:
reply: "Hello, world no. 0!"
reply: "Hello, world no. 1!"
reply: "Hello, world no. 2!"
reply: "Hello, world no. 3!"
reply: "Hello, world no. 4!"

Calling LotsOfGreetings:
reply: "Hello, A, B, C!"

Calling BidiHello:
reply: "Hello, A!"
reply: "Hello, B!"
reply: "Hello, C!"

Loading the Protobuf

The proto file is located at example/server/abc.proto

// file: example/server/abc.proto
syntax = "proto3";

package pyease.sample.v1;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloResponse);
  rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
  rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
  rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
}

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string reply = 1;
}

You can directly load this file using pyease_grpc without generating any stubs:

from pyease_grpc import Protobuf

protobuf = Protobuf.from_file("example/server/abc.proto")

Internally, it converts the proto file into FileDescriptorSet message.

It is recommended to use the FileDescriptorSet json to load the Protobuf faster.

To generate the FileDescriptorSet json from a proto file:

$ pyease-grpc -I example/server example/server/abc.proto --output abc_fds.json

Now you can use this descriptor file directly to create a Protobuf instance.

protobuf = Protobuf.restore_file('abc_fds.json')

Getting response from gRPC-Web

For Unary RPC request:

from pyease_grpc import RpcSession, RpcUri

session = RpcSession.from_file("example/server/abc.proto")
response = session.request(
    RpcUri(
      base_url="http://localhost:8080",
      package="pyease.sample.v1",
      service="Greeter",
      method="SayHello",
    ),
    {
      "name": "world"
    },
)
response.raise_for_status()

print(response.single['reply'])

For a Server-side Streaming RPC request:

from pyease_grpc import RpcSession, RpcUri

session = RpcSession.from_file("example/server/abc.proto")
response = session.request(
    RpcUri(
      base_url="http://localhost:8080",
      package="pyease.sample.v1",
      service="Greeter",
      method="LotsOfReplies",
    ),
    {
      "name": "world",
    },
)
response.raise_for_status()

for payload in response.iter_payloads():
    print(payload["reply"])

gRPC-Web currently supports 2 RPC modes: Unary RPCs, Server-side Streaming RPCs. Client-side and Bi-directional streaming is not currently supported.

Using the native gRPC protocol

You can also directly call a method using the native gRPC protocol.

For Unary RPC request:

from pyease_grpc import RpcSession, RpcUri

session = RpcSession.from_file("example/server/abc.proto")
response = session.call(
    RpcUri(
      base_url="localhost:50050",
      package="pyease.sample.v1",
      service="Greeter",
      method="SayHello",
    ),
    {
      "name": "world",
    }
)

print(response.single["reply"])
print(response.payloads)

For a Server-side Streaming RPC request:

from pyease_grpc import RpcSession, RpcUri

session = RpcSession.from_file("example/server/abc.proto")
response = session.call(
    RpcUri(
      base_url="localhost:50050",
      package="pyease.sample.v1",
      service="Greeter",
      method="LotsOfReplies",
    ),
    {
      "name": "world",
    },
)

for payload in response.iter_payloads():
    print(payload["reply"])
print(response.payloads)

For a Client-Side Streaming RPC request:

from pyease_grpc import RpcSession, RpcUri

session = RpcSession.from_file("example/server/abc.proto")
response = session.call(
    RpcUri(
      base_url="localhost:50050",
      package="pyease.sample.v1",
      service="Greeter",
      method="LotsOfGreetings",
    ),
    iter(
      [
        {"name": "A"},
        {"name": "B"},
        {"name": "C"},
      ]
    ),
)

print(response.single["reply"])
print(response.payloads)

For a Bidirectional Streaming RPC request:

from pyease_grpc import RpcSession, RpcUri

session = RpcSession.from_file("example/server/abc.proto")
response = session.call(
    RpcUri(
      base_url="localhost:50050",
      package="pyease.sample.v1",
      service="Greeter",
      method="BidiHello",
    ),
    iter(
      [
        {"name": "A"},
        {"name": "B"},
        {"name": "C"},
      ]
    ),
)

for payload in response.iter_payloads():
    print(payload["reply"])
print(response.payloads)

Error Handling

Errors are raised as soon as they appear.

List of errors that can appear during request:

  • ValueError: If the requested method, service or package is not found
  • requests.exceptions.InvalidHeader: If the header of expected length is not found
  • requests.exceptions.ContentDecodingError: If the data of expected length is not found
  • NotImplementedError: If compression is enabled in the response headers
  • grpc.RpcError: If the grpc-status is non-zero

List of errors that can appear during call:

  • ValueError: If the requested method, service or package is not found
  • grpc.RpcError: If the grpc-status is non-zero

To get the grpc-status and grpc-message, you can add a try-catch to your call. e.g.:

import grpc
from pyease_grpc import RpcSession, RpcUri

session = RpcSession.from_file("example/server/abc.proto")
rpc_uri = RpcUri(
  base_url="localhost:50050",
  package="pyease.sample.v1",
  service="Greeter",
  method="SayHello",
)
try:
  response = session.call(rpc_uri, {"name": "error"})
  print(response.single["reply"])
except grpc.RpcError as e:
  print('grpc status', e.code())
  print('grpc message', e.details())

Metadata

Release files for pyease-grpc 1.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyease-grpc 1.8.0
File Size Uploaded Provenance
pyease_grpc-1.8.0.tar.gz 23.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pyease-grpc 1.8.0
File Interpreter ABI Platform
pyease_grpc-1.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.5 kB

Release files / pyease_grpc-1.8.0.tar.gz

Download URL pyease_grpc-1.8.0.tar.gz
Size 23.3 kB
Tags Source
SHA-256 checksum
How to use checksums
e33bee6a0ca35bc41682d1c25243535a559cbbd6fcccdc9434e9f6f6cf3a8ee1
BLAKE2b-256 checksum
How to use checksums
4afdcb891e28d29833af26467504aff8b91d57a8d494e22dbcad3090ec81f4e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Release files / pyease_grpc-1.8.0-py3-none-any.whl

Download URL pyease_grpc-1.8.0-py3-none-any.whl
Size 20.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
69a05117cf88f310b37bf455b51a3fa352ea0a537d7894867a91eb744c6b27a1
BLAKE2b-256 checksum
How to use checksums
5c61c6115917527812eca3fd147cd389ef33a0bc342de7545c34f8125682e1aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Security for pyease-grpc 1.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pyease_grpc-1.8.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page