Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python global variable in fastApi not working as normal

I have a simple fastApi demo app which achieve a function: get different response json by calling a post api named changeResponse. The changeResponse api just changed a global variable, another api return different response through the same global variable.On local env,it works correctly, but the response always changed after i just call changeResponse once when i build this on docker.The code is as follows:

from typing import Optional
from fastapi import FastAPI
from util import read_json
import enum

app = FastAPI()

type = "00"
    
@app.post("/changeResponse")
async def handle_change_download_response(param:Optional[str]):
        global type
        type = param
        print("type is "+type)
        return {"success":"true"}

@app.post("/download")
async def handle_download(param:Optional[str]):
    print("get download param: "+param)
    if legalDownload(param):
        print("type is "+type)
        return read_json.readDownloadSuccessRes(type)
    else:
        return read_json.readDownloadFailRes()

def legalDownload(data:str)->bool:
    return True

the dockerfile is as follows:

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7

COPY ./app /app

what i except: call changeResponse param is 7, get response for 7, call changeResponse param is 8, get response for 8. what i get: call changeResponse param is 7,get reponse for 7,call changeReponse 8, sometime the response is 7, sometime is 8,impossible to predict

like image 755
rookie Avatar asked Sep 18 '20 04:09

rookie


People also ask

Why is my global variables are bad Python?

The reason global variables are bad is that they enable functions to have hidden (non-obvious, surprising, hard to detect, hard to diagnose) side effects, leading to an increase in complexity, potentially leading to Spaghetti code.

How do you reset global variables in Python?

You can change the value of a Python global variable by simply assigning it a new value (redeclaring). To delete a variable, use the keyword del .

Are global variables Pythonic?

In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function's body, it's assumed to be a local unless explicitly declared as global.


1 Answers

tiangolo/uvicorn-gunicorn-fastapi is based on uvicorn-gunicorn-docker image, which by defaults creates multiple workers. Excerpt from gunicorn_conf.py:

default_web_concurrency = workers_per_core * cores

Thus, the described situation arises because the request is processed by different workers (processes). Each of which has its own copy of the global variable

Update: If you want to change the count of workers, use the following environment variables:

  • WORKERS_PER_CORE: It will set the number of workers to the number of CPU cores multiplied by this value.
  • MAX_WORKERS: You can use it to let the image compute the number of workers automatically but making sure it's limited to a maximum.
  • WEB_CONCURRENCY Override the automatic definition of number of workers.

You can set it like:

docker run -d -p 80:80 -e WEB_CONCURRENCY="2" myimage

A more detailed description of these variables and examples here


If you want to share data between workers, pay attention to this topic.

like image 152
alex_noname Avatar answered Sep 19 '22 02:09

alex_noname