Bokeh server app with pyinstaller - Working

I have been fighting deployment with my application for awhile and I finally found a fix for pyinstaller working with a bokeh server and avoiding the dreaded “frozen module” issue that is listed in the common pitfalls on pyinstallers website. IE calling subprocesses like “bokeh serve --show <your_script>.py”

https://pyinstaller.org/en/latest/common-issues-and-pitfalls.html#launching-external-programs-from-the-frozen-application

I saw some posts from @Bryan referring to users having “some success” with pyinstaller but not much more then that. So, I wanted to share my discovery here so that we can all benefit a bit. It took me 3 and a half weeks to deploy my python app and the code was like 6 lines lol…

now, I am a self taught, no degree no college developer who talked his way into a web development lead role. So cut me some slack, but I will try to explain what is going on.

This was my previous code for running the bokeh server and updated the current document.

    if not curdoc().modify_doc_called:
        curdoc().add_next_tick_callback(lambda: modify_doc(curdoc()))
        curdoc().modify_doc_called = True
        print("Added modify_doc callback")

This code requires the subprocess call in the terminal to fire off. Which will cause pyinstallers frozen module issue.

With the help of our favorite AI GPT, I found a way to deploy the bokeh server with no subprocess calls and pure python.

def modify_doc(doc):
    print("modify_doc called")
    file_path = get_file_path()
    print(f"File path: {file_path}")
    if file_path:
        try:
            roof_dict = create_roof_tabs(file_path)
            if roof_dict:
                roof_panels = [v for v in roof_dict.values()]
                final_tabs = Tabs(tabs=roof_panels, sizing_mode='scale_both')
                doc.add_root(final_tabs)
            else:
                print("No panels were created.")
        except Exception as e:
            print(f"Error in modify_doc: {e}")
    else:
        print("No file selected.")

bokeh_app = Application(FunctionHandler(modify_doc))

def run_server():
    # Specify the port and address here if needed
    server = Server({'/': bokeh_app}, port=5006)
    server.start()
    server.io_loop.add_callback(server.show, "/")
    server.io_loop.start()

if __name__ == '__main__':
    run_server()

This resulted in a successful use of pyinstaller with a bokeh server. For reference, I also was able to utilize tkinter for file input as opposed to the bokeh server file input which forces 64 base encoding and temporary files etc. This meant that I was also able to utilize xlwings library for use of macros, formulas, and writing back to the existing excel because everything was still local.

Hopefully that helps some of you out with your bokeh/pyinstaller/xlwings needs!

1 Like

let me check the post from @Bryan then I will resolve your issue.