Add Python examples to most of the code blocks in bindings/index.mdx

This commit is contained in:
Hood Chatham 2025-12-11 15:45:50 -08:00
parent 36ad2112a7
commit ec4ecbb879
No known key found for this signature in database

View file

@ -8,7 +8,7 @@ description: Worker Bindings that allow for interaction with other Cloudflare Re
next: false
---
import { DirectoryListing, WranglerConfig } from "~/components";
import { DirectoryListing, TabItem, Tabs, WranglerConfig } from "~/components";
Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform. Bindings provide better performance and less restrictions when accessing resources from Workers than the [REST APIs](/api/) which are intended for non-Workers applications.
@ -31,9 +31,12 @@ r2_buckets = [
</WranglerConfig>
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
```js
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
await env.MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
@ -41,6 +44,22 @@ export default {
};
```
</TabItem> <TabItem label="Python" icon="seti:python">
```python
from workers import WorkerEntrypoint, Response
from urllib.parse import urlparse
class Default(WorkerEntrypoint):
async def fetch(self, request):
url = urlparse(request.url)
key = url.path.slice(1)
await self.env.MY_BUCKET.put(key, request.body)
return Response(f"Put {key} successfully!")
```
</TabItem></Tabs>
You can think of a binding as a permission and an API in one piece. With bindings, you never have to add secret keys or tokens to your Worker in order to access resources on your Cloudflare account — the permission is embedded within the API itself. The underlying secret is never exposed to your Worker's code, and therefore can't be accidentally leaked.
## Making changes to bindings
@ -94,6 +113,7 @@ Bindings are located on the `env` object, which can be accessed in several ways:
* It is as class property on [WorkerEntrypoint](/workers/runtime-apis/bindings/service-bindings/rpc/#bindings-env),
[DurableObject](/durable-objects/), and [Workflow](/workflows/):
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
```js
export class MyDurableObject extends DurableObject {
async sayHello() {
@ -101,13 +121,31 @@ Bindings are located on the `env` object, which can be accessed in several ways:
}
}
```
</TabItem> <TabItem label="Python" icon="seti:python">
```python
from workers import WorkerEntrypoint, Response
class Default(WorkerEntrypoint):
async def fetch(self, request):
return Response(f"Hi {self.env.NAME}")
```
</TabItem></Tabs>
* It can be imported from `cloudflare:workers`:
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
```js
import { env } from "cloudflare:workers";
console.log(`Hi, ${env.Name}`);
```
</TabItem> <TabItem label="Python" icon="seti:python">
```python
from workers import import_from_javascript
env = import_from_javascript("cloudflare:workers").env
print(f"Hi, {env.NAME}")
```
</TabItem></Tabs>
### Importing `env` as a global
@ -115,6 +153,7 @@ Importing `env` from `cloudflare:workers` is useful when you need to access a bi
such as [secrets](/workers/configuration/secrets/) or [environment variables](/workers/configuration/environment-variables/)
in top-level global scope. For example, to initialize an API client:
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
```js
import { env } from "cloudflare:workers";
import ApiClient from "example-api-client";
@ -129,6 +168,19 @@ export default {
},
};
```
</TabItem> <TabItem label="Python" icon="seti:python">
```python
from workers import WorkerEntrypoint, env
from example_api_client import ApiClient
api_client = ApiClient(api_key=env.API_KEY)
LOG_LEVEL = getattr(env, "LOG_LEVEL", "info")
class Default(WorkerEntrypoint):
async def fetch(self, request):
# ...
```
</TabItem></Tabs>
Workers do not allow I/O from outside a request context. This means that even
though `env` is accessible from the top-level scope, you will not be able to access
@ -139,6 +191,7 @@ call `env.NAMESPACE.get` to get a [Durable Object stub](/durable-objects/api/stu
top-level context. However, calling methods on the Durable Object stub, making [calls to a KV store](/kv/api/),
and [calling to other Workers](/workers/runtime-apis/bindings/service-bindings) will not work.
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
```js
import { env } from "cloudflare:workers";
@ -153,11 +206,26 @@ export default {
},
};
```
</TabItem> <TabItem label="Python" icon="seti:python">
```python
from workers import Response, WorkerEntrypoint, env
# This would fail!
# env.KV.get('my-key')
class Default(WorkerEntrypoint):
async def fetch(self, request):
# This works
mv_val = await env.KV.get("my-key")
return Response(my_val)
```
</TabItem></Tabs>
Additionally, importing `env` from `cloudflare:workers` lets you avoid passing `env`
as an argument through many function calls if you need to access a binding from a deeply-nested
function. This can be helpful in a complex codebase.
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
```js
import { env } from "cloudflare:workers";
@ -178,6 +246,24 @@ function getName() {
return env.MY_NAME;
}
```
</TabItem> <TabItem label="Python" icon="seti:python">
```python
from workers import Response, WorkerEntrypoint, env
class Default(WorkerEntrypoint):
def fetch(req):
return Response(say_hello())
# env is not an argument to say_hello...
def say_hello():
my_name = get_name()
return f"Hello, {myName}"
# ...nor is it an argument to getName
def get_name():
return env.MY_NAME
```
</TabItem></Tabs>
:::note
While using `env` from `cloudflare:workers` may be simpler to write than passing it
@ -194,6 +280,7 @@ Imagine a user has defined the [environment variable](/workers/configuration/env
`env.NAME` would print "Alice". Using the `withEnv` function, you can override the value of
"NAME".
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
```js
import { env, withEnv } from "cloudflare:workers";
@ -215,5 +302,24 @@ export default {
},
};
```
</TabItem> <TabItem label="Python" icon="seti:python">
```python
from workers import Response, WorkerEntrypoint, env, patch_env
def log_name():
print(env.NAME)
class Default(WorkerEntrypoint):
async def fetch(req):
# this will log "Alice"
log_name()
with patch_env(NAME="Bob"):
# this will log "Bob"
log_name()
# ...etc...
```
</TabItem></Tabs>
This can be useful when testing code that relies on an imported `env` object.