Search code examples
pythonfastapivercel

How can you specify python runtime version in vercel?


I am trying to deploy a simple FastAPI app to vercel for the first time. Vercel.json is exactly below.

{
  "devCommand": "uvicorn main:app --host 0.0.0.0 --port 3000",
  "builds": [
    {
      "src": "api/index.py",
      "use": "@vercel/python",
      "config": {
        "maxLambdaSize": "15mb",
        "runtime": "python3.9"
      }
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "api/index.py"
    }
  ]
}

I have specified runtime as python3.9, but this doesn't reflect actual runtime which is still python3.12 (default).This ends up causing internal error.

How can I configure runtime version correctly?

I also read the official docs which says builds property shouldn't be used. So I tried to rewrite like below.

{
  "devCommand": "uvicorn main:app --host 0.0.0.0 --port 3000",
  "functions": {
    "api/index.py":
    {
      "runtime": "[email protected]"
    }
  },
  "routes": [
    {
      "src": "/(.*)",
      "dest": "api/index.py"
    }
  ]
}

This didn't work as well. Maybe I shouldn't use vercel for python project?(little information in the internet)


Solution

  • I've scrolled through vercel docs but wasn't been able find any references that python version could be specified in builds or functions section of Vercel.json.

    • in 'builds' you specify npm package @vercel/python. I guess this is more like interface for node.js to run python3 scripts.
    • in 'functions' you kind off specify serverless functions. I'm not sure that this is what you need.

    Ref: https://vercel.com/docs/projects/project-configuration

    Solution:

    However as it is listed in Vercel documentation python version could be defined in the Pipfile.

    Ref: https://vercel.com/docs/functions/runtimes/python

    Note Vercel only supports python 3.12 (default) and python 3.9 (requires legacy image i.e. use Node.js 16 or 18.)

    Vercel Manuals:

    This links might be useful for setting up your first python project on vercel: https://github.com/vercel/examples/tree/main/python/hello-world
    https://github.com/vercel/examples/tree/main/python/flask3
    https://github.com/vercel/examples/tree/main/python

    What worked for me

    First create your http handler or flask app or else:

    ## my_app.py
    from http.server import BaseHTTPRequestHandler, HTTPServer
    import sys
    
    class GETHandler(BaseHTTPRequestHandler):
     
        def do_GET(self):
            self.send_response(200)
            self.send_header('Content-type','text/plain')
            self.end_headers()
            self.wfile.write('Hello, world!\n'.encode('utf-8'))
            python_version = f"{sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}"
            self.wfile.write(f'Python version {python_version}'.encode('utf-8'))
    
    # variable required by Vercel
    handler = GETHandler
    

    Next create a Pipfile. This bash commands will automatically create a Pipfile.

    ## run in bash
    pip install pipenv
    pipenv install
    

    Automatically generated pipfile should look smth like this:

    ## Pipfile
    [[source]]
    url = "https://pypi.org/simple"
    verify_ssl = true
    name = "pypi"
    
    [packages]
    pipenv = "~=2023.12"
    
    [dev-packages]
    
    [requires]
    python_version = "3.9"
    

    Next create package.json. You need to set node.js version to 18.x for running your scripts in python 3.9.

    ## package.json
    {
        "engines": {
          "node": "18.x"
        }
        
    }
    

    Third, you need to define routes that will trigger executing python server:

    ## vercel.json
    {
    "builds": [
        { "src": "*.py", "use": "@vercel/python" }
      ],
      "redirects": [
        { "source": "/", "destination": "/my_app.py" }
      ]  
    
    }
    

    Finally let's set up Deployment Settings. In my project settings I don't add any run or build commands:

    enter image description here

    However for python 3.9 check that your node.js version is 18.x (same page, i.e. in the Deployment Settings).

    enter image description here

    That's it. After the deployment visit the generated route link and it will automatically redirect you to /my_app.py. You can see that python 3.9 was used to generate the page:

    enter image description here