cloudflare / workerd

The JavaScript / Wasm runtime that powers Cloudflare Workers
https://blog.cloudflare.com/workerd-open-source-workers-runtime/
Apache License 2.0
6.23k stars 301 forks source link

πŸ› BUG: python FastAPI worker: ModuleNotFoundError: No module named 'httpx' #2396

Open yym68686 opened 3 months ago

yym68686 commented 3 months ago

Which Cloudflare product(s) does this pertain to?

Workers Runtime

What version(s) of the tool(s) are you using?

wrangler 3.63.2

What version of Node are you using?

v20.13.1

What operating system and version are you using?

Mac 14.4.1

Describe the Bug

Observed behavior

display

✘ [ERROR] A request to the Cloudflare API (/accounts/8ec0d42e9131e125b020b6d4918fe721/workers/scripts/uni-api) failed.

  Uncaught Error: PythonError: Traceback (most recent call last):
    File "/lib/python312.zip/_pyodide/_base.py", line 629, in pyimport_impl
      res = __import__(stem, fromlist=fromlist)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/session/metadata/main.py", line 3, in <module>
      import httpx
  ModuleNotFoundError: No module named 'httpx'

    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:9998) in new_error
    at [object Object] in $wrap_exception
    at [object Object] in $pythonexc2js
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:607956) in Module._pythonexc2js
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:64098) in
  Module.callPyObjectKwargs
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:65055) in Module.callPyObject
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:79132) in apply
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:77371) in apply
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:102862) in pyimport
    at null.<anonymous> (pyodide:python-entrypoint-helper:31:18) in pyimportMainModule
   [code: 10021]

  If you think this is a bug, please open an issue at:
  https://github.com/cloudflare/workers-sdk/issues/new/choose

Expected behavior

No error, can import the httpx module

Steps to reproduce

Please provide the following:

import httpx
from contextlib import asynccontextmanager
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
    timeout = httpx.Timeout(connect=10.0, read=30.0, write=30.0, pool=30.0)
    app.state.client = httpx.AsyncClient(timeout=timeout)
    yield
    await app.state.client.aclose()

app = FastAPI(lifespan=lifespan)

@app.get("/generate-api-key")
def generate_api_key():
    return {"api_key": "hello world"}

async def on_fetch(request, env):
    import asgi

    return await asgi.fetch(app, request, env)

An error occurred immediately after executing wrangler deploy.

A git repo we can clone and run a test suite on, or which has a README with step-by-step instructions, is even better. In this case, please use the field below to provide a link to the minimal repro.

Please provide a link to a minimal reproduction

No response

Please provide any relevant error logs

 ⛅️ wrangler 3.63.2
-------------------

β–² [WARNING] The entrypoint main.py defines a Python worker, support for Python workers is currently experimental.

Attaching additional modules:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Name                                β”‚ Type   β”‚ Size     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ .wrangler/tmp/deploy-dpY4MJ/main.py β”‚ python β”‚ 0.58 KiB β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ main copy.py                        β”‚ python β”‚ 9.98 KiB β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ models.py                           β”‚ python β”‚ 1.20 KiB β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ request.py                          β”‚ python β”‚ 8.74 KiB β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ response.py                         β”‚ python β”‚ 7.15 KiB β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ test/launch_with_clear.py           β”‚ python β”‚ 0.18 KiB β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Total Upload: 28.40 KiB / gzip: 6.28 KiB

✘ [ERROR] A request to the Cloudflare API (/accounts/8ec0d42e9131e125b020b6d4918fe721/workers/scripts/uni-api) failed.

  Uncaught Error: PythonError: Traceback (most recent call last):
    File "/lib/python312.zip/_pyodide/_base.py", line 629, in pyimport_impl
      res = __import__(stem, fromlist=fromlist)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/session/metadata/main.py", line 1, in <module>
      import httpx
  ModuleNotFoundError: No module named 'httpx'

    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:9998) in new_error
    at [object Object] in $wrap_exception
    at [object Object] in $pythonexc2js
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:607956) in Module._pythonexc2js
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:64098) in
  Module.callPyObjectKwargs
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:65055) in Module.callPyObject
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:79132) in apply
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:77371) in apply
    at null.<anonymous> (pyodide-internal:generated/pyodide.asm:20:102862) in pyimport
    at null.<anonymous> (pyodide:python-entrypoint-helper:31:18) in pyimportMainModule
   [code: 10021]

  If you think this is a bug, please open an issue at:
  https://github.com/cloudflare/workers-sdk/issues/new/choose
dom96 commented 3 months ago

What does your requirements.txt file look like? It doesn't look like you have one defined

yym68686 commented 3 months ago

Yes, because requirements.txt is not supported now, I did not add the requirements.txt file.

dom96 commented 3 months ago

requirements.txt is the only way we support these packages, they cannot be deployed yet but it will be possible soon.

yym68686 commented 3 months ago

Thank you for the reply. I hope to use requirements.txt to deploy the project as soon as possible. Do you have a specific timeline? A month, six months, or a year?

mmabrouk commented 3 months ago

@dom96 Seconding @yym68686 question. Any broad timeline ?

afeezaziz commented 3 months ago

@dom96 Seconding @yym68686 question. Any broad timeline ?

@dom96 does this mean that we cannot deploy fastapi apps in the example at the moment?

mikenomitch commented 3 months ago

Hey @yym68686, @mmabrouk, & @afeezaziz,

Regarding timing on package support, I think a very rough estimate would be something like 6 months for open beta package support in prod. We don’t have a firm date, but in any case, I wouldn’t build something today with the expectation that this is just around the corner.

Some context is that current Python startup times with packages are long enough where we think cold starts would impact end-users regularly in a non-trivial way. We are working on two things: reducing cold start length and reducing cold start frequency for Python. We’ve got a good plan on both (pre-initializing isolates with Pyodide and loading package memory snapshots to reduce time & smartly routing requests to re-use Workers that are already loaded), but it’ll take some time to execute on this.

Sorry if that timeline is disappointing. It is longer than we wanted it to be on our end as well.

mmabrouk commented 2 months ago

Thanks for the quick answer @mikenomitch ! Looking forward to it. I think if you get this right, cloudflare could become the place to host genAI applications.