🐡

Cloudflare Workers が Python をサポートしたのでやってみる。

2024/04/10に公開

今日は以下の発表内容をやってみます。
https://blog.cloudflare.com/python-workers

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 を実行させることが可能となります。

やってみた

では早速やってみます。
https://developers.cloudflare.com/workers/languages/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を以下に書き換えます。

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.jsworker.pyにリネームして以下の内容に置換します。

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を以下に書き換えます。

worker.py
from hello import hello
from js import Response

def on_fetch(request):
    return Response.new(hello("World"))

Helloモジュールを新たに宣言し、Worldという文字列引数を渡しています。以下のようにhello.pyを作ります。

hello.py
def hello(name):
    return "Hello, " + name + "!"

再度Deployすると無事文字列が連結されてHello, World!と表示されます。

また、js workers と同様に環境変数も使うことが出来ます。wrangler.tomlに以下を追記します。

wrangler.toml
[vars]
API_HOST = "example.com"
worker.py
from js import Response

async def on_fetch(request, env):
    return Response.new(env.API_HOST)

に編集して再度デプロイすると環境変数が画面に表示され、正しく内部で渡されていることがわかります。

Discussion