Error loading layout after migration from python2 to python3

Hello!

Excited to write my first post on the community,

The dashboard is importing the data from an Postgresql.
Here is the code:

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
import pathlib
import pandas as pd 
import dash_table as dt
from sqlalchemy import create_engine
from dash.dependencies import Input, Output, State
import unicodedata


#Path


BASE_PATH = pathlib.Path(__file__).parent.resolve()



app = dash.Dash(__name__)
server = app.server
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True

def import_dataframe_db():
    engine = create_engine(url)
    df= pd.read_sql_table('table',engine)
    return df

def delete_empty_colums(df):
    empty_cols = df.columns[df.isnull().all()]
    df.drop(columns=empty_cols,axis=1,inplace=True)
    return df

def list_the_columns(df):
    colmn_names = list(df.columns)
    return colmn_names

def get_number_unique_values_pd(df):
    unq_df = df.nunique()
    unq_df = pd.DataFrame(unq_df).reset_index()
    unq_df.columns = ['Keyword','Counts']
    return unq_df



def options_dropdown_keyowrds():
    df = import_dataframe_db()
    dff = delete_empty_colums(df)
    dff.columns = dff.columns.astype(str)
    options = []
    for i in dff.columns:
        options.append(i.encode('utf8'))
    return options

def genarate_uq_table(dataframe,max_rows=5):
    return html.Table(
        [html.Tr([html.Th(col) for col in dataframe.columns])] +
        [html.Tr([
            html.Td(sorted(dataframe[col].unique())) for col in dataframe.columns
        ]) for i in range(min(len(dataframe), max_rows))]
    )

def generate_frontpage():

    return html.Div(
        id="las-header",
        children = [
            html.Img(id="las-logo", src=app.get_asset_url("logo.png")),
            html.Div(
                id="las-header-text",
                children=[
                    html.H1("Actus AG Report"),
                    html.Div(
                        id="las-file-info",
                        children=[
                            html.Span(id="las-filename",children="Some Test")
                        ]
                    )
                ]
            )
        ]
    )

def generate_histo_uq():
    df = import_dataframe_db()
    df= delete_empty_colums(df)
    df_u = get_number_unique_values_pd(df)
    fig = px.scatter(df_u,x='Keyword',y='Counts')
    return fig


def generate_table_uq_values():
    df = import_dataframe_db()
    df= delete_empty_colums(df)
    df_u = get_number_unique_values_pd(df)
    return dt.DataTable(
        id="table",
        sort_action = 'native',
        filter_action="native",
        editable=True,
        css= [{
            'selector' : 'table',
            "rule" : "display: inline; white-space: inherit; overflow: inherit; text-overflow: inherit;"
            }]
            ,
        style_data={'whiteSpace':'normal'},
        style_cell = {
            "padding": "15px",
            "midWidth" : "0px",
            "width" : "25%",
            "textAlign":"center",
            "border" : "white",
        },
    
    
        columns = [{"name" : i.strip().decode(), "id": i.strip().decode()} for i in df_u.columns],
        data = df_u.to_dict("rows")
    )

df = import_dataframe_db()
df= delete_empty_colums(df)
app.layout = html.Div(
    [
        html.Div(id="frontpage",className='page',children=generate_frontpage()),
        html.Div(
            className='section',
            children = [
                html.Div(className="section-title",children="Unique Values"),
                html.Div(
                    className="page",
                    children= [
                        html.Div(id="las-table",children=generate_table_uq_values()),
                        html.Div(id="las-table-print"),
                    ],
                ),
            ],

        ),
    html.Div(
        className="section",
        children=[
            html.Div(className='section-title',children="Scatter Plot"),
            html.Div([
                dcc.Graph(id = 'graph_size',figure = generate_histo_uq(),
                style = {'height': "750px"})],
            ),

        ]
    ),
    html.Div(
        className = "section",
        children = [
            
            html.Div(className='section-title',children="Return the unique values of each column "),
            html.Div(
            dcc.Dropdown(
                id='keyword_dropdown',
                options=[{'label': i.strip().decode() ,'value': i.strip().decode()} for i in  options_dropdown_keyowrds()],
                multi=True,
                placeholder='Filter by column:'
            ),style={}),
            html.Div(id='table-container')
    ]
    )
    ]
)
        


@app.callback(
    Output('table-container','children'),
    [Input('keyword_dropdown','value')]
)
def update_dropdown(drop_down_value):
    if drop_down_value is None:
        return None
    return genarate_uq_table(df[drop_down_value])

if __name__ == '__main__':
    app.run_server(debug=True)

I was running the app perfectly on python2.
When i upgraded on python3 i encounter this error from the gunicorn app:

Exception on /_dash-layout [GET]
Traceback (most recent call last):
TypeError: Object of type bytes is not JSON serializable
Exception on /_dash-layout [GET]
Traceback (most recent call last):
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/dash/dash.py", line 512, in serve_layout
    json.dumps(layout, cls=plotly.utils.PlotlyJSONEncoder),
  File "/usr/lib/python3.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/_plotly_utils/utils.py", line 45, in encode
    encoded_o = super(PlotlyJSONEncoder, self).encode(o)
  File "/usr/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/home/ntousis/.virtualenvs/dash_python3/lib/python3.7/site-packages/_plotly_utils/utils.py", line 115, in default
    return _json.JSONEncoder.default(self, obj)
  File "/usr/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type bytes is not JSON serializable

Can not deserialize a bytes object but the data are all unicoded: u ’ Data '.

The app gives:

Error loading layout

Any help pleaseee?

Looks like you haven’t posted all the code, however based on contextual clues, I’d guess you’re pulling data from external source(s), and the driver is returning data in bytes in python3, where the same code was returning str in python2.

If your code doesn’t use bytes anywhere, look at all the calls reading from external data sources and check their return types. If you’re using sqlalchemy, make sure the encoding for your DB backend is set correctly, or just identify which pandas column(s) is of types bytes, and encode it to str:

df['<bytes column>'].apply(lambda x: x.decode("utf-8"))

Appreciate aschmitz, i was encoding the lines from the dash components and not the actual dataframe :exploding_head: .

1 Like