{"id":715,"library":"thrift","title":"Apache Thrift Python Bindings","description":"Apache Thrift is a lightweight, language-independent RPC framework designed to enable seamless cross-language communication between services. It provides abstractions for data transport, serialization, and application-level processing. The Python bindings allow developers to build interoperable RPC clients and servers from a common Interface Definition Language (IDL). The current version is 0.22.0, with releases typically occurring a few times a year.","status":"active","version":"0.22.0","language":"python","source_language":"en","source_url":"https://github.com/apache/thrift","tags":["rpc","serialization","cross-language","client-server","idl"],"install":[{"cmd":"pip install thrift","lang":"bash","label":"Install core library"}],"dependencies":[{"reason":"Optional backend for Tornado-based servers/clients.","package":"python-tornado","optional":true},{"reason":"Optional backend for Twisted-based servers/clients.","package":"python-twisted","optional":true},{"reason":"Required to generate Python code from .thrift IDL files.","package":"Apache Thrift Compiler (C++ executable)","optional":false}],"imports":[{"symbol":"TSocket","correct":"from thrift.transport import TSocket"},{"symbol":"TBufferedTransport","correct":"from thrift.transport import TBufferedTransport"},{"symbol":"TBinaryProtocol","correct":"from thrift.protocol import TBinaryProtocol"},{"note":"TSimpleServer, TThreadPoolServer, etc., are attributes of the TServer module, not direct imports in many examples. The correct import is usually 'from thrift.server import TServer', then access TServer.TSimpleServer().","wrong":"from thrift.server import TSimpleServer","symbol":"TSimpleServer","correct":"from thrift.server import TServer"},{"symbol":"TException","correct":"from thrift import Thrift; Thrift.TException"}],"quickstart":{"code":"# 1. Define your service in 'calculator.thrift'\n# namespace py tutorial\n# service Calculator {\n#     i32 add(1:i32 num1, 2:i32 num2),\n#     void ping()\n# }\n\n# 2. Generate Python code using the Thrift compiler:\n#    thrift --gen py calculator.thrift\n# This creates a 'gen-py' directory with 'tutorial' module.\n\nimport sys\nimport os\nimport time\n\n# Ensure 'gen-py' is on the path to import generated code\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nsys.path.insert(0, os.path.join(current_dir, 'gen-py'))\n\n# Generated code imports\nfrom tutorial import Calculator\nfrom tutorial.ttypes import *\n\n# Thrift core library imports\nfrom thrift.transport import TSocket, TTransport\nfrom thrift.protocol import TBinaryProtocol\nfrom thrift.server import TServer\n\n# --- Server Implementation ---\nclass CalculatorHandler:\n    def __init__(self):\n        self.log = {}\n\n    def ping(self):\n        print('Server: ping()')\n\n    def add(self, num1, num2):\n        print(f'Server: add({num1}, {num2})')\n        return num1 + num2\n\ndef start_server():\n    handler = CalculatorHandler()\n    processor = Calculator.Processor(handler)\n    transport = TSocket.TServerSocket(host='127.0.0.1', port=9090)\n    tfactory = TTransport.TBufferedTransportFactory()\n    pfactory = TBinaryProtocol.TBinaryProtocolFactory()\n\n    server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)\n    print('Starting the server on port 9090...')\n    # In a real application, you might run this in a separate process or thread\n    # For this quickstart, we'll simulate a long-running server\n    # server.serve() # This blocks\n    return server # Return server for demonstration, typically would call serve()\n\n# --- Client Implementation ---\ndef run_client():\n    # Make socket\n    transport = TSocket.TSocket('localhost', 9090)\n    # Buffering is critical. Raw sockets are very slow\n    transport = TTransport.TBufferedTransport(transport)\n    # Wrap in a protocol\n    protocol = TBinaryProtocol.TBinaryProtocol(transport)\n    # Create a client to use the protocol encoder\n    client = Calculator.Client(protocol)\n\n    # Connect!\n    try:\n        transport.open()\n        print('Client: Connected to server.')\n        client.ping()\n        print('Client: ping() sent.')\n\n        sum_result = client.add(5, 7)\n        print(f'Client: 5 + 7 = {sum_result}')\n\n    except TException as tx:\n        print(f'Client: Error: {tx.message}')\n    finally:\n        transport.close()\n        print('Client: Connection closed.')\n\nif __name__ == '__main__':\n    # This part demonstrates server setup and a client call in sequence.\n    # For actual usage, server and client would typically run in separate processes.\n    server_instance = start_server()\n    # In a real scenario, you would start the server in a background thread or process.\n    # For simplicity, we'll run the client immediately assuming the server is ready.\n    # You might need a small delay for the server to fully start in a real async scenario.\n    print(\"Quickstart: Server started (not blocking), running client now...\")\n    run_client()\n    print(\"Quickstart: Client finished. If server was blocking, it would still be running.\")\n    # If server_instance.serve() was called, you'd need a way to stop it.\n","lang":"python","description":"To use Apache Thrift in Python, you first define your service in a `.thrift` IDL file. Then, you use the Apache Thrift compiler (a C++ executable, not `pip install thrift`) to generate Python client and server stubs from this IDL. The generated code lives in a `gen-py` directory. The example demonstrates a simple `Calculator` service with `add` and `ping` methods, showing basic server and client setup."},"warnings":[{"fix":"Re-generate Python code from `.thrift` files using the `thrift` compiler version 0.22.0 or newer. Review generated code and update client/server implementations to match any altered patterns or class names in the generated stubs or core library.","message":"Apache Thrift 0.22.0 introduced significant breaking changes for some language bindings (e.g., .NET Standard namespace and class name changes like `TServerSocket` to `TServerSocketTransport`, `TSimpleServer` to `TSimpleAsyncServer`). While the core Python API hasn't seen as many direct breaking changes in naming within the `thrift` package itself for this version, applications might still need adjustments, especially if depending on specific compiler flag behaviors or generated code specifics that were updated. Always re-generate Python code with the latest compiler for consistency.","severity":"breaking","affected_versions":"0.22.0 and later"},{"fix":"Install the Apache Thrift compiler executable (`thrift`) separately from the Python library. Consult the official Apache Thrift documentation for instructions on installing the compiler for your operating system.","message":"The `pip install thrift` package provides only the Python runtime libraries. It DOES NOT include the `thrift` compiler (a C++ executable) which is absolutely necessary to generate Python client/server stub code from your `.thrift` IDL files. This compiler must be installed separately (e.g., via a package manager like `apt`, `brew`, or by building from source).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Choose one implementation (`thrift` or `thriftpy`/`thriftpy2`) and stick to its API and workflow. If using the official `thrift`, always use the `thrift --gen py` command to generate code before importing.","message":"Do not confuse the official `thrift` library (which requires code generation) with `thriftpy` or `thriftpy2`. `thriftpy`/`thriftpy2` are alternative, pure Python implementations that can dynamically load `.thrift` files at runtime without a separate compiler step. Attempting to use `thriftpy`'s dynamic loading or API (`thriftpy.load()`) with the official `thrift` library will lead to `AttributeError` or `ImportError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For production, consider installing the generated Python code as a proper Python package (e.g., using `setuptools` and defining the generated directory as a package) or ensuring it's part of your application's installable modules that are correctly added to `PYTHONPATH`.","message":"When importing generated Thrift code, examples often use `sys.path.append('gen-py')` to make the generated modules discoverable. While functional for quickstarts, this is not a best practice for production environments as it bypasses standard Python packaging mechanisms and can lead to module resolution issues.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T18:14:14.003Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Add the directory containing the generated Python modules to `sys.path` at runtime or ensure it's part of your `PYTHONPATH` environment variable before importing. Example: `import sys; sys.path.append('./gen-py'); from your_service_name.ttypes import MyStruct`","cause":"The Python interpreter cannot find the modules generated by the `thrift` compiler because the directory containing them (e.g., `gen-py`) is not in `sys.path`.","error":"ModuleNotFoundError: No module named 'your_service_name.ttypes'"},{"fix":"Install the Apache Thrift compiler using your system's package manager (e.g., `sudo apt-get install thrift-compiler` on Debian/Ubuntu, `brew install thrift` on macOS) or by building it from source.","cause":"The Apache Thrift compiler executable is not installed on the system or is not present in the system's PATH environment variable.","error":"sh: thrift: command not found"},{"fix":"Ensure the Thrift server is running and listening on the specified host and port, and verify network connectivity and firewall rules.","cause":"The Thrift client failed to establish a connection with the Thrift server, typically because the server is not running, is listening on a different host/port, or a firewall is blocking the connection.","error":"thrift.transport.TTransportException: Could not connect to host localhost:9090"},{"fix":"Ensure both the Thrift client and server are configured to use the exact same protocol factory (e.g., both use `TBinaryProtocol.TBinaryProtocolFactory` or both use `TCompactProtocol.TCompactProtocolFactory`).","cause":"The Thrift client and server are configured to use different protocol implementations, leading to a mismatch in how messages are serialized and deserialized.","error":"thrift.protocol.TProtocolException: Bad version in readMessageBegin"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":"0.22.0","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.3,"disk_size":"20.0M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.3,"disk_size":"20.0M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":2.3,"import_time_s":0.01,"mem_mb":1.3,"disk_size":"20M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":1.3,"disk_size":"20M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.5,"disk_size":"22.6M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.5,"disk_size":"22.6M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":2.4,"import_time_s":0.05,"mem_mb":1.5,"disk_size":"23M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.5,"disk_size":"23M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.3,"disk_size":"12.5M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.3,"disk_size":"12.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":3.3,"import_time_s":0.04,"mem_mb":1.3,"disk_size":"13M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.3,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.6,"disk_size":"12.2M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.6,"disk_size":"12.1M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":3,"import_time_s":0.04,"mem_mb":1.4,"disk_size":"13M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.4,"disk_size":"13M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.2,"disk_size":"19.6M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.2,"disk_size":"19.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"sdist","failure_reason":null,"install_time_s":2.8,"import_time_s":0.02,"mem_mb":1.2,"disk_size":"20M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.2,"disk_size":"20M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}