diff --git a/src/content/changelog/workers/2025-05-14-python-worker-durable-object.mdx b/src/content/changelog/workers/2025-05-14-python-worker-durable-object.mdx
index 0ac40bc24c22e0c..0467f5159f0f0fe 100644
--- a/src/content/changelog/workers/2025-05-14-python-worker-durable-object.mdx
+++ b/src/content/changelog/workers/2025-05-14-python-worker-durable-object.mdx
@@ -18,7 +18,7 @@ long-running applications which run close to your users. For more info see
You can define a Durable Object in Python in a similar way to JavaScript:
```python
-from workers import DurableObject, Response, handler
+from workers import DurableObject, Response, WorkerEntrypoint
from urllib.parse import urlparse
@@ -27,17 +27,17 @@ class MyDurableObject(DurableObject):
self.ctx = ctx
self.env = env
- def on_fetch(self, request):
+ def fetch(self, request):
result = self.ctx.storage.sql.exec("SELECT 'Hello, World!' as greeting").one()
return Response(result.greeting)
-@handler
-async def on_fetch(request, env, ctx):
- url = urlparse(request.url)
- id = env.MY_DURABLE_OBJECT.idFromName(url.path)
- stub = env.MY_DURABLE_OBJECT.get(id)
- greeting = await stub.fetch(request.url)
- return greeting
+class Default(WorkerEntrypoint):
+ async def fetch(self, request, env, ctx):
+ url = urlparse(request.url)
+ id = env.MY_DURABLE_OBJECT.idFromName(url.path)
+ stub = env.MY_DURABLE_OBJECT.get(id)
+ greeting = await stub.fetch(request.url)
+ return greeting
```
Define the Durable Object in your Wrangler configuration file:
diff --git a/src/content/changelog/workers/2025-08-14-new-python-handlers.mdx b/src/content/changelog/workers/2025-08-14-new-python-handlers.mdx
new file mode 100644
index 000000000000000..e4e13e561790838
--- /dev/null
+++ b/src/content/changelog/workers/2025-08-14-new-python-handlers.mdx
@@ -0,0 +1,33 @@
+---
+title: Python Workers handlers now live in an entrypoint class
+description: We are changing how Python Workers are structured by default.
+products:
+ - workers
+date: 2025-08-14
+---
+
+import { WranglerConfig } from "~/components";
+
+We are changing how Python Workers are structured by default. Previously, handlers were defined at the top-level of a module as `on_fetch`, `on_scheduled`, etc. methods, but now they live in an entrypoint class.
+
+Here's an example of how to now define a Worker with a fetch handler:
+
+```python
+from workers import Response, WorkerEntrypoint
+
+class Default(WorkerEntrypoint):
+ async def fetch(self, request, env, ctx):
+ return Response("Hello World!")
+```
+
+To keep using the old-style handlers, you can specify the `disable_python_no_global_handlers` compatibility flag in your wrangler file:
+
+
+
+```toml
+compatibility_flags = [ "disable_python_no_global_handlers" ]
+```
+
+
+
+Consult the [Python Workers documentation](/workers/languages/python/) for more details.
\ No newline at end of file
diff --git a/src/content/docs/d1/examples/query-d1-from-python-workers.mdx b/src/content/docs/d1/examples/query-d1-from-python-workers.mdx
index 59165521c4141e2..cb87c543c31d0b9 100644
--- a/src/content/docs/d1/examples/query-d1-from-python-workers.mdx
+++ b/src/content/docs/d1/examples/query-d1-from-python-workers.mdx
@@ -81,15 +81,16 @@ The value of `binding` is how you will refer to your database from within your W
To create a Python Worker, create an empty file at `src/entry.py`, matching the value of `main` in your Wrangler file with the contents below:
```python
-from workers import Response
+from workers import Response, WorkerEntrypoint
-async def on_fetch(request, env):
- # Do anything else you'd like on request here!
+class Default(WorkerEntrypoint):
+ async def fetch(self, request, env):
+ # Do anything else you'd like on request here!
- # Query D1 - we'll list all tables in our database in this example
- results = await env.DB.prepare("PRAGMA table_list").run()
- # Return a JSON response
- return Response.json(results)
+ # Query D1 - we'll list all tables in our database in this example
+ results = await env.DB.prepare("PRAGMA table_list").run()
+ # Return a JSON response
+ return Response.json(results)
```
diff --git a/src/content/docs/durable-objects/get-started.mdx b/src/content/docs/durable-objects/get-started.mdx
index 8d307aa9afda65c..1d6e98390a63de8 100644
--- a/src/content/docs/durable-objects/get-started.mdx
+++ b/src/content/docs/durable-objects/get-started.mdx
@@ -185,16 +185,16 @@ export default {
```python
-from workers import handler, Response
+from workers import handler, Response, WorkerEntrypoint
from urllib.parse import urlparse
-@handler
-async def on_fetch(request, env, ctx):
- url = urlparse(request.url)
- id = env.MY_DURABLE_OBJECT.idFromName(url.path)
- stub = env.MY_DURABLE_OBJECT.get(id)
- greeting = await stub.say_hello()
- return Response(greeting)
+class Default(WorkerEntrypoint):
+ async def fetch(request, env, ctx):
+ url = urlparse(request.url)
+ id = env.MY_DURABLE_OBJECT.idFromName(url.path)
+ stub = env.MY_DURABLE_OBJECT.get(id)
+ greeting = await stub.say_hello()
+ return Response(greeting)
```
@@ -328,13 +328,13 @@ class MyDurableObject(DurableObject):
return result.greeting
-@handler
-async def on_fetch(request, env, ctx):
- url = urlparse(request.url)
- id = env.MY_DURABLE_OBJECT.idFromName(url.path)
- stub = env.MY_DURABLE_OBJECT.get(id)
- greeting = await stub.say_hello()
- return Response(greeting)
+class Default(WorkerEntrypoint):
+ async def fetch(self, request, env, ctx):
+ url = urlparse(request.url)
+ id = env.MY_DURABLE_OBJECT.idFromName(url.path)
+ stub = env.MY_DURABLE_OBJECT.get(id)
+ greeting = await stub.say_hello()
+ return Response(greeting)
```
diff --git a/src/content/docs/workers/examples/103-early-hints.mdx b/src/content/docs/workers/examples/103-early-hints.mdx
index 471ed7302b38c9c..ec14e6fa12d05de 100644
--- a/src/content/docs/workers/examples/103-early-hints.mdx
+++ b/src/content/docs/workers/examples/103-early-hints.mdx
@@ -116,7 +116,7 @@ export default {
```py
import re
-from workers import Response
+from workers import Response, WorkerEntrypoint
CSS = "body { color: red; }"
HTML = """
@@ -132,12 +132,14 @@ HTML = """