Install & Compatibility
Where this runs
tested against v0.0.7 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.362s · 25.7MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.8s · import 0.316s · 27MB
24MB installed
● package 24MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
TwirpASGIApp
✓ from twirp.asgi import TwirpASGIApp
InvalidArgument
✓ from twirp.exceptions import InvalidArgument
TwirpServerException
✓ from twirp.exceptions import TwirpServerException
Context
✓ from twirp.context import Context
A Twirp service is defined in a `.proto` file. The `protoc` compiler, along with the `protoc-gen-twirpy` plugin, generates Python server and client stubs from this definition. You then implement the service logic in a Python class and expose it via a `TwirpASGIApp`. The example demonstrates a simple `HaberdasherService` and illustrates how to set up the ASGI application. For a complete, runnable example, you would need to define `haberdasher.proto` and generate the `haberdasher_twirp` and `haberdasher_pb2` modules.
import random
from twirp.asgi import TwirpASGIApp
from twirp.exceptions import InvalidArgument
from twirp.context import Context
# Assuming you have a haberdasher.proto and generated code like this:
# protoc --python_out=. --twirpy_out=. haberdasher.proto
# from . import haberdasher_twirp, haberdasher_pb2
# For demonstration, we'll mock these imports
# Mocking generated code for quickstart demonstration
class MockHat:
def __init__(self, size, color, name):
self.size = size
self.color = color
self.name = name
class MockSize:
def __init__(self, inches):
self.inches = inches
class MockHaberdasherPb2:
def Hat(self, size, color, name):
return MockHat(size, color, name)
class MockHaberdasherTwirp:
class HaberdasherServer:
def __init__(self, service, server_path_prefix='/twirp'):
self.service = service
self.server_path_prefix = server_path_prefix
class HaberdasherClient:
def __init__(self, base_url, server_path_prefix='/twirp'):
self.base_url = base_url
self.server_path_prefix = server_path_prefix
def MakeHat(self, ctx, request):
# In a real scenario, this would make an HTTP call
print(f"Client: Making hat for size {request.inches} inches")
# Simulate a successful response
return MockHat(size=request.inches, color="mock_color", name="mock_hat")
haberdasher_pb2 = MockHaberdasherPb2()
haberdasher_twirp = MockHaberdasherTwirp()
class HaberdasherService(object):
def MakeHat(self, context, size):
if size.inches <= 0:
raise InvalidArgument(argument="inches", error="I can't make a hat that small!")
return haberdasher_pb2.Hat(
size=size.inches,
color=random.choice(["white", "black", "brown", "red", "blue"]),
name=random.choice(["bowler", "baseball cap", "top hat", "derby"])
)
# Server setup
service = haberdasher_twirp.HaberdasherServer(service=HaberdasherService())
app = TwirpASGIApp()
app.add_service(service)
print("Twirp server (mocked) app created. Run with 'uvicorn your_module:app --port=3000' (after code generation).")
# Client usage (demonstrative, requires running server)
# client = haberdasher_twirp.HaberdasherClient("http://localhost:3000")
# try:
# response = client.MakeHat(ctx=Context(), request=haberdasher_pb2.Size(inches=12))
# print(f"Client received: {response.name} {response.color} hat, size {response.size}")
# except TwirpServerException as e:
# print(f"Client error: {e.code} - {e.message}")
Debug
Known issues
breakingTwirp Wire Protocol v7 introduces breaking changes from v5, notably affecting server URL prefixes. The default prefix is now `/twirp`, but custom prefixes can be set via `server_path_prefix` in server and client constructors. Ensure compatibility when upgrading or interacting with services using different protocol versions.fixReview and update server URL prefixes in both server and client configurations. Explicitly set `server_path_prefix` if a custom prefix is desired, or ensure consistency with the default `/twirp`.
affects: All versions supporting v7 protocol (e.g., twirp 0.0.7 / twirpy 0.1.0+).
gotchaThe `twirp` Python package provides the runtime library, but the actual server/client code generation requires the `protoc` compiler and the `protoc-gen-twirpy` Go plugin, which must be installed separately.fixInstall `protoc` (e.g., `brew install protobuf` on macOS) and the `protoc-gen-twirpy` plugin (e.g., `go install github.com/verloop/twirpy/protoc-gen-twirpy@latest`) and ensure `protoc-gen-twirpy` is in your system's PATH before attempting code generation.
affects: All versions.
gotchaThe default maximum message body length is 100KB. Larger messages will result in errors unless this limit is explicitly overridden.fixFor services handling large messages, increase the `max_receive_message_length` parameter when constructing `TwirpASGIApp` (e.g., `app = TwirpASGIApp(max_receive_message_length=1024 * 1024)` for 1MB).
affects: All versions.
gotchaThe `twirp` PyPI package (version 0.0.7) is effectively a wrapper for the `twirpy` project. While `twirp` 0.0.7 mentions support for Protocol v7, active development and newer versions (e.g., 0.3.0.dev2) are found under the `twirpy` PyPI package. This can cause confusion regarding the 'latest' version or documentation sources.fixFor the most up-to-date features and bug fixes, consider installing `twirpy` directly (`pip install twirpy`) and referring to its documentation and GitHub repository. Be aware of potential versioning discrepancies and ensure your generated code and runtime library are compatible.
affects: Users of `twirp` PyPI package 0.0.7 and potentially older versions of `twirpy`.
Upgrade
Version history
0.0.7latest on PyPI · released Apr 24, 2022
Audit
Dependencies
uvicornrequiredASGI server to run Twirp services.
protobufrequiredProtocol Buffers runtime and compiler (protoc) are essential for defining services and generating code. The `protoc-gen-twirpy` plugin is also required for Python code generation.