Cloudflare Workers が Python をサポートしたのでやってみる。
今日は以下の発表内容をやってみます。
Cloudflare Workers が Python をサポートしました。Workers はWeb Assembly をサポートしており、Pythonなどの言語を持ち込むことは可能でした。今回の発表によりPythonのランタイムがWorkers の基本機能として提供されるため、Web Assembly を用いる必要がなくなります。
Workers は Chromium v8 JavaScriptエンジンで構成されておりNativeでPythonが実行可能なわけではありません。ではどのように実装されているのでしょうか。
Pyodide ってなに?
Pyodideを用いて実装している、が答えです。Pyodideとはなんでしょうか?
単純には、CPython を Web Assembly 化した実行環境です。 Pyodide を Web ページに読み込むことで、JavaScript から Python コードを実行することができるようになります。これによりChronium v8 エンジン上で Python の実行をサポートしています。
CPython ってなに?
CPython は Python と何が違うのか?やっぱり特殊なんじゃないか!と思われる方もいるかもしれないです。Python という言語使用を C言語をもちいて実装したものが CPython です。最も一般的な Python実装であり、一般的には特に指定されない限り Python = CPython と言ってしまって問題ないレベルで使われています。
これらの組み合わせにより一般的なブラウザの JavaScript エンジンを用いて Python を実行させることが可能となります。
やってみた
では早速やってみます。
に Getting Started がありますのでそちらをやってみます。まずは普通に Wrangler を用いて Workers の新規プロジェクトを起こします。
以下を参考に実行してみて下さい。
wrangler init
Delegating to locally-installed wrangler@3.10.0 over global wrangler@2.14.0...
Run `npx wrangler init` to use the local version directly.
⛅️ wrangler 3.10.0 (update available 3.48.0)
-------------------------------------------------------
Using npm as package manager.
▲ [WARNING] The `init` command is no longer supported. Please use `npm create cloudflare@2` instead.
The `init` command will be removed in a future version.
Running `npm create cloudflare@2`...
using create-cloudflare version 2.0.9
╭ Create an application with Cloudflare Step 1 of 3
│
├ Where do you want to create your application?
│ dir pythontest
│
├ What type of application do you want to create?
│ type "Hello World" script
│
├ Do you want to use TypeScript?
│ typescript no
│
├ Copying files from "simple" template
│
├ Do you want to use git?
│ git no
│
╰ Application created
╭ Installing dependencies Step 2 of 3
│
├ Installing dependencies
│ installed via `npm install`
│
╰ Dependencies Installed
╭ Deploy with Cloudflare Step 3 of 3
│
├ Do you want to deploy your application?
│ no deploying via `npm run deploy`
│
├ APPLICATION CREATED Deploy your application with npm run deploy
│
│ Run the development server npm run start
│ Deploy your application npm run deploy
│ Read the documentation https://developers.cloudflare.com/workers
│ Stuck? Join us at https://discord.gg/cloudflaredev
│
╰ See you again soon!
wrangler.toml
を以下に書き換えます。
name = "pythontest"
main = "src/worker.py"
compatibility_date = "2024-03-18"
compatibility_flags = ["python_workers"]
具体的には、
1.main
で読み込むコードファイルをjs
からpy
に変更
2.compatibility_date
の日付を"2024-03-18"
に変更
これは、Workers側で読み込むPyodideランタイムのバージョンを指定するパラメータです
3.compatibility_flags = ["python_workers"]
を追加
これにより明示的にWorkersにこの関数は Python を利用することを宣言します。
次にすでに作成済のworker.js
をworker.py
にリネームして以下の内容に置換します。
from js import Response
def on_fetch(request):
return Response.new("Hello World!")
wrangler deploy
を実行しデプロイします。
wrangler deploy
Delegating to locally-installed wrangler@3.48.0 over global wrangler@2.14.0...
Run `npx wrangler deploy` to use the local version directly.
⛅️ wrangler 3.48.0
-------------------
▲ [WARNING] The entrypoint src\worker.py defines a Python worker, support for Python workers is currently experimental.
√ Select an account » Harunobukameda Demo account
Total Upload: 0.08 KiB / gzip: 0.09 KiB
Uploaded pythontest (5.82 sec)
Published pythontest (3.76 sec)
https://pythontest.harunobukameda.workers.dev
Current Deployment ID: 9ae9c0c3-408b-41f0-8c5e-bdba44c24d54
NOTE: "Deployment ID" in this output will be changed to "Version ID" in a future version of Wrangler. To learn more visit: https://developers.cloudflare.com/workers/configuration/versions-and-deployments
出力された URL (上の例でいうとhttps://pythontest.harunobukameda.workers.dev/
)にアクセスするとHello World
が表示されます。
では次にworker.py
を以下に書き換えます。
from hello import hello
from js import Response
def on_fetch(request):
return Response.new(hello("World"))
Hello
モジュールを新たに宣言し、World
という文字列引数を渡しています。以下のようにhello.py
を作ります。
def hello(name):
return "Hello, " + name + "!"
再度Deployすると無事文字列が連結されてHello, World!
と表示されます。
また、js workers と同様に環境変数も使うことが出来ます。wrangler.toml
に以下を追記します。
[vars]
API_HOST = "example.com"
from js import Response
async def on_fetch(request, env):
return Response.new(env.API_HOST)
に編集して再度デプロイすると環境変数が画面に表示され、正しく内部で渡されていることがわかります。
Discussion