Search code examples
pythonpython-3.xsanic

LIGHTGBM pickle output not working with multiple SANIC workers (>1) but working with single worker


I am trying to load machine learning model output with Sanic. I have loaded the output in the main method(defined globally). It works fine when I set sanic worker as 1 but not not working with multiple sanic workers when defined globally. My code waits for indefinite time for model to generate desired result.

Its works when I load model output inside the function (e.g. here in the method modelrun) even if sanic workers >= 1

It works when I load model output globally(outside the function) but only if sanic workers = 1

It doesnot work when I load model output globally(outside the function) if sanic workers > 1

import pickle
import sanic

if __name__ == '__main__':
    df = pd.DataFrame()

    p_file_path = "/Users/pratiksha/FModel_06Jan_Smote_Sel_Vars_48.dat"
    pickle_file = open(path, 'rb')
    lbg_model_smote_sel_vars = pickle.load(pickle_file)

    modelrun(df, lbg_model_smote_sel_vars)

    app.run(host=app_host, port=int(app_port), debug=True,
            auto_reload=True, workers=int(10))


def modelrun(df_f, lbg_model_smote_sel_vars):
    training_pred_smote = lbg_model_smote_sel_vars.predict_proba(df_f)
    return training_pred_smote

Versions Used

  1. sanic==20.12.1

  2. lightgbm==3.3.1

  3. numpy==1.20.1

  4. pandas==1.2.4

  5. scikitlearn==1.0.2

  6. scipy==1.6.2


Solution

  • Upgrade Sanic Version to 21.12.1

    When you have multiple workers, Sanic will start a main process that manages several subprocesses. These subprocesses will be the application server workers.

    Check out the cycle here. https://sanicframework.org/en/guide/basics/listeners.html

    After loading the pickle, it seems to be solved by adding it to the context property.

    ex.

    # or main_process_start
    @app.listener("before_server_start")
    async def startup(app, loop):
        loaded = pickle.load(your_file)
        app.ctx.pickle = loaded
    
    @app.get("/")
    async def handler(request):
        # Call pickle
        request.app.ctx.pickle