workerd icon indicating copy to clipboard operation
workerd copied to clipboard

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

Open yym68686 opened this issue 1 year ago β€’ 8 comments

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:

  • A minimal working subset of your worker code
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)
  • A minimal working subset of your wrangler.toml
name = "uni-api"
main = "main.py"
compatibility_flags = ["python_workers"]
compatibility_date = "2024-03-20"
  • Commands used to start your local dev server, including custom env and cli args
wrangler deploy
  • Steps to be performed in the browser, curl commands, or a test we can run that reliably fails (at least a percent of the time)

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

yym68686 avatar Jul 10 '24 07:07 yym68686

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

dom96 avatar Jul 15 '24 15:07 dom96

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

yym68686 avatar Jul 16 '24 03:07 yym68686

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

dom96 avatar Jul 22 '24 13:07 dom96

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?

yym68686 avatar Jul 23 '24 07:07 yym68686

@dom96 Seconding @yym68686 question. Any broad timeline ?

mmabrouk avatar Jul 28 '24 15:07 mmabrouk

@dom96 Seconding @yym68686 question. Any broad timeline ?

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

afeezaziz avatar Jul 31 '24 08:07 afeezaziz

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.

mikenomitch avatar Jul 31 '24 17:07 mikenomitch

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.

mmabrouk avatar Aug 09 '24 07:08 mmabrouk

@mikenomitch is there any update on the open beta?

HackyRoot avatar Dec 29 '24 06:12 HackyRoot

Is there any new progress?

Dylan-Li8 avatar Mar 18 '25 10:03 Dylan-Li8

They are running a close beta program for packages in production. You need to apply by submitting a form. They are supporting 50+ packages rn, and other packages can be vendored.

Check out this message on Discord: https://discord.com/channels/595317990191398933/1224715939581530112/1351242879061856388

HackyRoot avatar Mar 21 '25 05:03 HackyRoot

https://blog.cloudflare.com/python-workers/

https://developers.cloudflare.com/workers/languages/python/packages/

yym68686 avatar Apr 03 '25 06:04 yym68686