Python and JavaScript Workers can now call each other via RPC
You can now call methods between Python and JavaScript Workers using Workers RPC. This works through Service bindings without extra dependencies, schema definitions, or serialization code.
Cross-language RPC calls behave like ordinary function calls. Exceptions propagate to the call site. You can pass structured cloneable types ↗ as parameters or return values, and Pyodide Foreign Function Interface (FFI) automatically converts types between languages.
Define a method in a TypeScript Worker:
import { WorkerEntrypoint } from "cloudflare:workers";
export class RpcService extends WorkerEntrypoint {
async add(a, b) {
return a + b;
}
}import { WorkerEntrypoint } from "cloudflare:workers";
export class RpcService extends WorkerEntrypoint {
async add(a: number, b: number): Promise<number> {
return a + b;
}
}Call it from a Python Worker through a Service binding:
from workers import Response, WorkerEntrypoint
class Default(WorkerEntrypoint):
async def fetch(self, request):
rpc = self.env.RPC
result = await rpc.add(42, 144)
return Response.json({"result": result})Configure the Service binding in the Python Worker's Wrangler configuration:
{
"services": [
{
"binding": "RPC",
"service": "ts-rpc-server",
"entrypoint": "RpcService"
}
]
}[[services]]
binding = "RPC"
service = "ts-rpc-server"
entrypoint = "RpcService"Define a method in a Python Worker:
from workers import WorkerEntrypoint
class Default(WorkerEntrypoint):
async def highlight_code(self, code: str, language: str) -> dict:
from pygments.formatters import HtmlFormatter
from pygments import highlight
from pygments.lexers import get_lexer_by_name
lexer = get_lexer_by_name(language, stripall=True)
formatter = HtmlFormatter(linenos=True, cssclass="highlight", style="monokai")
highlighted_html = highlight(code, lexer, formatter)
css = formatter.get_style_defs(".highlight")
return {
"html": highlighted_html,
"css": css
}Call it from a JavaScript Worker through a Service binding:
export default {
async fetch(request, env) {
const rpc = env.PYTHON_RPC;
const result = await rpc.highlight_code("print(42)", "python");
return Response.json(result);
},
};export default {
async fetch(request, env) {
const rpc = env.PYTHON_RPC;
const result = await rpc.highlight_code("print(42)", "python");
return Response.json(result);
},
};Configure the Service binding in the JavaScript Worker's Wrangler configuration:
{
"services": [
{
"binding": "PYTHON_RPC",
"service": "py-rpc-server"
}
]
}[[services]]
binding = "PYTHON_RPC"
service = "py-rpc-server"For more details on the announcement, read the blog post ↗.
For more information, refer to the Workers RPC documentation and the Python Workers overview.