Heroku Deployment Error

Hello,

I am attempting to deploy my dash app to heroku, but I am getting an error. The app runs fine locally.

Here is my code:

import pandas as pd
import numpy as np
from pandas import DataFrame

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table as dt
from dash.dependencies import Input, Output, State

import flask

import plotly.express as px
import plotly.graph_objs as go

import time
import datetime

import warnings
warnings.filterwarnings(‘ignore’)

import dash_bootstrap_components as dbc

rxshort = pd.read_csv(‘https://raw.githubusercontent.com/adamagovino/rx-app/main/rx_short.csv’)

df = rxshort
drug_array = df[‘Drug_Name’].unique()
drug_list = drug_array.tolist()

Bootswatch · BootstrapCDN

server = flask.Flask(name)
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], server=server)

#app = dash.Dash(name, external_stylesheets=[dbc.themes.BOOTSTRAP],
#meta_tags=[{‘name’: ‘viewport’,
#‘content’: ‘width=device-width, initial-scale=1.0’}])
#server = app.server

Layout section: Bootstrap (Bootstrap 4 Cheat Sheet - The ultimate list of Bootstrap classes)

************************************************************************

app.layout = dbc.Container([

dbc.NavbarSimple(
children=[
    dbc.NavItem(dbc.NavLink("Page 1", href="#")),
    dbc.DropdownMenu(
        children=[
            dbc.DropdownMenuItem("More pages", header=True),
            dbc.DropdownMenuItem("Page 2", href="#"),
            dbc.DropdownMenuItem("Page 3", href="#"),
        ],
        nav=True,
        in_navbar=True,
        label="More",
    ),
],
brand="NavbarSimple",
brand_href="#",
color="primary",
dark=True,

),

    #Title
    dbc.Row(
        dbc.Col(html.H2("Med Reimbursement Genie",
                        className='text-center text-primary mb-4'),
                width=12)
    ), 

    dbc.Row([
        dbc.Col(html.Label(['Choose Med:'],style={'font-weight': 'bold', "text-align": "center"})),
        dbc.Col(html.Label(['Choose Plan:'],style={'font-weight': 'bold', "text-align": "center"}))
    ]),

    #Choose Med & Plan
    dbc.Row([ 
        dbc.Col(dcc.Dropdown(id='meds-dpdn', multi=False, value='FLUOXETINE 20MG CAP',
                    options=[{'label':x, 'value':x}
                    for x in sorted(drug_list)]),
                    #width={'size': 5, "offset": 1, 'order': 1}
               ),

        dbc.Col(dcc.Dropdown(id='plans-dpdn',
                    options=[]),
                    #width={'size': 5, "offset": 0, 'order': 2}
               )
    ]),

    
    
    html.Div([
        dcc.Tabs([
            dcc.Tab(label='Best Reimbursed NDC For This Strength', children=

                    dbc.Col([
                        html.Div(id="table1"
                                )]
                    )

            ),
        
                   

            dcc.Tab(label='Best Reimbursed NDC For This Indication', children=

                    dbc.Col([
                        html.Div(id='table2'
                                )]
                    )
            ),
            
                   

            dcc.Tab(label='Best Reimbursed NDC For This Class', children=
    
                    dbc.Col([
                        html.Div(id='table3'
                                )]
                    )
            )
    
        ])
    ])

])

######CALLBACKS########

@app.callback(
Output(‘plans-dpdn’, ‘options’),
[Input(‘meds-dpdn’, ‘value’)]
)
def plans(chosen_plan):
dff = df[df.Drug_Name==chosen_plan]
return [{‘label’: c, ‘value’: c} for c in sorted(dff.Plan.unique())]

@app.callback(
Output(‘plans-dpdn’, ‘value’),
[Input(‘plans-dpdn’, ‘options’)]
)
def plans_value(available_options):
return [x[‘value’] for x in available_options]

#Table based on same drug and strength
@app.callback(
Output(‘table1’, ‘children’),
[Input(‘plans-dpdn’, ‘value’)],
[State(‘meds-dpdn’, ‘value’)],
)

def update_table(plan,med):

filt_exact = df[df['Drug_Name']==med]
ndc = filt_exact['NDC'].iloc[0]
brand_gen = filt_exact['Brand/Generic'].iloc[0]

if len(filt_exact) < 1:
    print ('Drug Not Found')

else:
    split_name = (med.split())[0]
    first6 = split_name[0:6].lower().replace(' ','')
    filt_med = df[(df['Drug Name First6']==first6) & (df['Plan']==plan)]

    strength = df[df['Drug_Name']==med]['Strength'].iloc[0]
    filt_strength = filt_med[filt_med['Strength']==strength]

    if (len(filt_med) < 1) or (len(filt_strength) <1):
        
        data = {'This Medicine Does not Have Enough Comps to Make a Table or Something Else iS Wrong':  ['First value']}

        end_function_df = pd.DataFrame(data, columns = ['This Medicine Doesnt Have Accurate Comps'])
        
        print("Drug and/or Strength Not Found Using This Plan")
        
        return html.Div([dt.DataTable(
            data=end_function_df.to_dict('rows'),
            columns=[{'name': i, 'id': i} for i in end_function_df.columns],
            ),
            html.Hr()
                        ])

    else:
        med_class = filt_exact['New_Class'].iloc[0]
        indication1 = filt_exact['Indication_One'].iloc[0]
        indication2 = filt_exact['Indication_Two'].iloc[0]
        indications = [indication1,indication2]
        route = filt_exact['Route'].iloc[0]

        filt_class = df[(df['New_Class']==med_class) & (df['Plan']==plan) & (df['Route']==route)]
        filt_ind = df[(df['Indication_One']==indication1) | (df['Indication_One']==indication2) | (df['Indication_Two']==indication1) | (df['Indication_Two']==indication2)]

        #Table based on same drug and strength
        ndcs = list(set(filt_strength['NDC']))
        ndc_list = []
        spu_list = []
        date_list = []
        for ndc in ndcs:
            ndc_list.append(ndc)
            filtst = filt_strength[filt_strength['NDC']==ndc]
            filtst.sort_values(by=['Date'], inplace=True, ascending=False)
            latest_spu = filtst['SPU'].iloc[0]
            latest_date = filtst['Date'].iloc[0]
            spu_list.append(latest_spu)
            date_list.append(latest_date)

        ndc_df = pd.DataFrame({'NDC':ndc_list,'Spread':spu_list,'Date':date_list})
        ndc_df.sort_values(by=['Spread'], inplace=True, ascending=False)

        
        filt_strength['Date'] = pd.to_datetime(filt_strength.Date)
        filt_strength.sort_values(by=['Date'], inplace=True, ascending=False) # This now sorts in date order
        fig = px.line(filt_strength, x="Date", y="SPU", title = 'Reimbursement Trend')
        graph = dcc.Graph(figure=fig)
        
        return html.Div([dt.DataTable(
            data=ndc_df.to_dict('rows'),
            columns=[{'name': i, 'id': i} for i in ndc_df.columns],
            ),
            html.Hr()
                        ]), graph

#Table based on Same Indication
@app.callback(
Output(‘table2’, ‘children’),
[Input(‘plans-dpdn’, ‘value’)],
[State(‘meds-dpdn’, ‘value’)],
)

def update_table2(plan,med):

filt_exact = df[df['Drug_Name']==med]
ndc = filt_exact['NDC'].iloc[0]
brand_gen = filt_exact['Brand/Generic'].iloc[0]

if len(filt_exact) < 1:
    print ('Drug Not Found')

else:
    split_name = (med.split())[0]
    first6 = split_name[0:6].lower().replace(' ','')
    filt_med = df[(df['Drug Name First6']==first6) & (df['Plan']==plan)]

    strength = df[df['Drug_Name']==med]['Strength'].iloc[0]
    filt_strength = filt_med[filt_med['Strength']==strength]

    if (len(filt_med) < 1) or (len(filt_strength) <1):
        
        data = {'This Medicine Does not Have Enough Comps to Make a Table or Something Else iS Wrong':  ['First value']}

        end_function_df = pd.DataFrame(data, columns = ['This Medicine Doesnt Have Accurate Comps'])
        
        print("Drug and/or Strength Not Found Using This Plan")
        
        return html.Div([dt.DataTable(
            data=end_function_df.to_dict('rows'),
            columns=[{'name': i, 'id': i} for i in end_function_df.columns],
            ),
            html.Hr()
                        ])

    #2) filtering out by 1) same med+strength 2) same med, any strength, 3) same class (any med any strength)
    else:
        med_class = filt_exact['New_Class'].iloc[0]
        indication1 = filt_exact['Indication_One'].iloc[0]
        indication2 = filt_exact['Indication_Two'].iloc[0]
        indications = [indication1,indication2]
        route = filt_exact['Route'].iloc[0]

        filt_class = df[(df['New_Class']==med_class) & (df['Plan']==plan) & (df['Route']==route)]
        filt_ind = df[(df['Indication_One']==indication1) | (df['Indication_One']==indication2) | (df['Indication_Two']==indication1) | (df['Indication_Two']==indication2)]
        
        #Table based on Indication
        ndci = list(set(filt_ind['NDC']))
        ndci_list = []
        spui_list = []
        datei_list = []
        medi_list = []
        for ndc in ndci:
            ndci_list.append(ndc)
            filti = filt_ind[filt_ind['NDC']==ndc]
            filti.sort_values(by=['Date'], inplace=True, ascending=False)
            latest_spui = filti['SPU'].iloc[0]
            latest_datei = filti['Date'].iloc[0]
            med_namei = filti['Drug_Name'].iloc[0]
            spui_list.append(latest_spui)
            datei_list.append(latest_datei)
            medi_list.append(med_namei)

        ndci_df = pd.DataFrame({'Med':medi_list,'NDC':ndci_list,'Spread':spui_list,'Date':datei_list})
        ndci_df.sort_values(by=['Spread'], inplace=True, ascending=False)
        ndci_df = ndci_df.head()
        
        return html.Div([dt.DataTable(
            data=ndci_df.to_dict('rows'),
            columns=[{'name': i, 'id': i} for i in ndci_df.columns],
            ),
            html.Hr()
                        ])

#Table based on same class
@app.callback(
Output(‘table3’, ‘children’),
[Input(‘plans-dpdn’, ‘value’)],
[State(‘meds-dpdn’, ‘value’)],
)

def update_table3(plan,med):

filt_exact = df[df['Drug_Name']==med]
ndc = filt_exact['NDC'].iloc[0]
brand_gen = filt_exact['Brand/Generic'].iloc[0]

if len(filt_exact) < 1:
    print ('Drug Not Found')

else:
    split_name = (med.split())[0]
    first6 = split_name[0:6].lower().replace(' ','')
    filt_med = df[(df['Drug Name First6']==first6) & (df['Plan']==plan)]

    strength = df[df['Drug_Name']==med]['Strength'].iloc[0]
    filt_strength = filt_med[filt_med['Strength']==strength]
    
    if (len(filt_med) < 1) or (len(filt_strength) <1):
        
        data = {'This Medicine Does not Have Enough Comps to Make a Table or Something Else iS Wrong':  ['First value']}

        end_function_df = pd.DataFrame(data, columns = ['This Medicine Doesnt Have Accurate Comps'])
        
        print("Drug and/or Strength Not Found Using This Plan")
        
        return html.Div([dt.DataTable(
            data=end_function_df.to_dict('rows'),
            columns=[{'name': i, 'id': i} for i in end_function_df.columns],
            ),
            html.Hr()
                        ])

    else:
        med_class = filt_exact['New_Class'].iloc[0]
        indication1 = filt_exact['Indication_One'].iloc[0]
        indication2 = filt_exact['Indication_Two'].iloc[0]
        indications = [indication1,indication2]
        route = filt_exact['Route'].iloc[0]

        filt_class = df[(df['New_Class']==med_class) & (df['Plan']==plan) & (df['Route']==route)]
        filt_ind = df[(df['Indication_One']==indication1) | (df['Indication_One']==indication2) | (df['Indication_Two']==indication1) | (df['Indication_Two']==indication2)]

        #Table based on same class
        ndcc = list(set(filt_class['NDC']))
        ndcc_list = []
        spuc_list = []
        datec_list = []
        med_list = []
        for ndc in ndcc:
            ndcc_list.append(ndc)
            filtcl = filt_class[filt_class['NDC']==ndc]
            filtcl.sort_values(by=['Date'], inplace=True, ascending=False)
            latest_spuc = filtcl['SPU'].iloc[0]
            latest_datec = filtcl['Date'].iloc[0]
            med_name = filtcl['Drug_Name'].iloc[0]
            spuc_list.append(latest_spuc)
            datec_list.append(latest_datec)
            med_list.append(med_name)

        ndcc_df = pd.DataFrame({'Med':med_list,'NDC':ndcc_list,'Spread':spuc_list,'Date':datec_list})
        ndcc_df.sort_values(by=['Spread'], inplace=True, ascending=False)
        ndcc_df_short = ndcc_df[:5]
        
        return html.Div([dt.DataTable(
            data=ndcc_df_short.to_dict('rows'),
            columns=[{'name': i, 'id': i} for i in ndcc_df.columns],
            ),
            html.Hr()
                        ])

if name == ‘main’:
app.run_server(debug=True)

And here is the error message on Heroku:

2021-03-15T02:47:43.679690+00:00 heroku[web.1]: State changed from crashed to starting

2021-03-15T02:47:53.200258+00:00 heroku[web.1]: Starting process with command gunicorn app:app

2021-03-15T02:47:55.631988+00:00 app[web.1]: [2021-03-15 02:47:55 +0000] [4] [INFO] Starting gunicorn 20.0.4

2021-03-15T02:47:55.632801+00:00 app[web.1]: [2021-03-15 02:47:55 +0000] [4] [INFO] Listening at: http://0.0.0.0:20831 (4)

2021-03-15T02:47:55.632981+00:00 app[web.1]: [2021-03-15 02:47:55 +0000] [4] [INFO] Using worker: sync

2021-03-15T02:47:55.639206+00:00 app[web.1]: [2021-03-15 02:47:55 +0000] [9] [INFO] Booting worker with pid: 9

2021-03-15T02:47:55.653707+00:00 app[web.1]: [2021-03-15 02:47:55 +0000] [10] [INFO] Booting worker with pid: 10

2021-03-15T02:47:56.059774+00:00 heroku[web.1]: State changed from starting to up

2021-03-15T02:48:01.568149+00:00 app[web.1]: Application object must be callable.

2021-03-15T02:48:01.568504+00:00 app[web.1]: [2021-03-15 02:48:01 +0000] [10] [INFO] Worker exiting (pid: 10)

2021-03-15T02:48:01.761452+00:00 app[web.1]: Application object must be callable.

2021-03-15T02:48:01.761676+00:00 app[web.1]: [2021-03-15 02:48:01 +0000] [9] [INFO] Worker exiting (pid: 9)

2021-03-15T02:48:01.908182+00:00 app[web.1]: Traceback (most recent call last):

2021-03-15T02:48:01.908269+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 209, in run

2021-03-15T02:48:01.908778+00:00 app[web.1]: self.sleep()

2021-03-15T02:48:01.908812+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 357, in sleep

2021-03-15T02:48:01.909209+00:00 app[web.1]: ready = select.select([self.PIPE[0]], , , 1.0)

2021-03-15T02:48:01.909243+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 242, in handle_chld

2021-03-15T02:48:01.909552+00:00 app[web.1]: self.reap_workers()

2021-03-15T02:48:01.909584+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 528, in reap_workers

2021-03-15T02:48:01.910023+00:00 app[web.1]: raise HaltServer(reason, self.APP_LOAD_ERROR)

2021-03-15T02:48:01.910205+00:00 app[web.1]: gunicorn.errors.HaltServer: <HaltServer ‘App failed to load.’ 4>

2021-03-15T02:48:01.910233+00:00 app[web.1]:

2021-03-15T02:48:01.910234+00:00 app[web.1]: During handling of the above exception, another exception occurred:

2021-03-15T02:48:01.910234+00:00 app[web.1]:

2021-03-15T02:48:01.910263+00:00 app[web.1]: Traceback (most recent call last):

2021-03-15T02:48:01.910293+00:00 app[web.1]: File “/app/.heroku/python/bin/gunicorn”, line 8, in

2021-03-15T02:48:01.910517+00:00 app[web.1]: sys.exit(run())

2021-03-15T02:48:01.910547+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py”, line 58, in run

2021-03-15T02:48:01.910795+00:00 app[web.1]: WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()

2021-03-15T02:48:01.910824+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/app/base.py”, line 228, in run

2021-03-15T02:48:01.911143+00:00 app[web.1]: super().run()

2021-03-15T02:48:01.911173+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/app/base.py”, line 72, in run

2021-03-15T02:48:01.911412+00:00 app[web.1]: Arbiter(self).run()

2021-03-15T02:48:01.911442+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 229, in run

2021-03-15T02:48:01.911730+00:00 app[web.1]: self.halt(reason=inst.reason, exit_status=inst.exit_status)

2021-03-15T02:48:01.911754+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 342, in halt

2021-03-15T02:48:01.912149+00:00 app[web.1]: self.stop()

2021-03-15T02:48:01.912181+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 393, in stop

2021-03-15T02:48:01.912573+00:00 app[web.1]: time.sleep(0.1)

2021-03-15T02:48:01.912602+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 242, in handle_chld

2021-03-15T02:48:01.912903+00:00 app[web.1]: self.reap_workers()

2021-03-15T02:48:01.912932+00:00 app[web.1]: File “/app/.heroku/python/lib/python3.7/site-packages/gunicorn/arbiter.py”, line 528, in reap_workers

2021-03-15T02:48:01.913448+00:00 app[web.1]: raise HaltServer(reason, self.APP_LOAD_ERROR)

2021-03-15T02:48:01.913600+00:00 app[web.1]: gunicorn.errors.HaltServer: <HaltServer ‘App failed to load.’ 4>

2021-03-15T02:48:02.000000+00:00 app[api]: Build succeeded

2021-03-15T02:48:02.002165+00:00 heroku[web.1]: Process exited with status 1

2021-03-15T02:48:02.070405+00:00 heroku[web.1]: State changed from up to crashed

2021-03-15T02:48:14.395408+00:00 heroku[router]: at=error code= H10 desc=“App crashed” method= GET path="/" host=my-rxtool.herokuapp.com request_id=add4825f-7eea-4bcd-a98e-2eb4966f71d4 fwd=“74.90.2.120” dyno= connect= service= status=503 bytes= protocol=https

2021-03-15T02:48:14.842788+00:00 heroku[router]: at=error code= H10 desc=“App crashed” method= GET path="/favicon.ico" host=my-rxtool.herokuapp.com request_id=88041e75-22dd-4230-9ef8-b0579e815ef9 fwd=“74.90.2.120” dyno= connect= service= status=503 bytes= protocol=https

Hi @adama
What’s you app file called and what did you assign to gunicorn?

@adamschroeder

App file is called app.py…

My procfile is: ‘web: gunicorn app:app’

HI @adama
I’m not if that’s the problem, but I have it as the following:

my app file is called “datatable.py” and inside of it I have:

app = dash.Dash(__name__)
server = app.server

And inside my Procfile I have:

web: gunicorn datatable:server

Is yours similar? Could that be the problem?

p.s. make sure to capitalize “Procfile”

@adamschroeder my Procfile specs pointed to :app instead of :server - thank you!

1 Like