pyjulia icon indicating copy to clipboard operation
pyjulia copied to clipboard

OSError: access violation when calling Julia code in Dash app

Open crabbixOCE opened this issue 3 years ago • 12 comments

Trying to call any julia code from inside a Dash app results in OSError: exception: access violation reading 0x0000000000000018.

This error occurs no matter what code I try to call, even things like Julia().eval("2+2") so I know it's not a result of Julia errors.

My current workaround is running a second Quart app and sending POST requests to trigger asynchronous callbacks containing my Julia functions, which for some reason actually allow me to run my julia code. It seems ridiculous that I can't simply run my Julia code inside the dash app and if there's a known fix to this I'd very much like to hear it.

crabbixOCE avatar Oct 26 '22 21:10 crabbixOCE

Can you provide a minimum working example?

mkitti avatar Nov 23 '22 02:11 mkitti

I am having the exact same issue. JuliaCall has a similar issue

magnusbbc avatar Mar 20 '23 19:03 magnusbbc

I need specific steps to reproduce, please.

mkitti avatar Mar 20 '23 19:03 mkitti

sure!

Here is a minimum example (modified from here)

from dash import Dash, dcc, html, Input, Output
from julia import Main

app = Dash(__name__)

app.layout = html.Div([
    html.H6("Change the value in the text box to see callbacks in action!"),
    html.Div([
        "Input: ",
        dcc.Input(id='my-input', value='initial value', type='text')
    ]),
    html.Br(),
    html.Div(id='my-output'),

])


@app.callback(
    Output(component_id='my-output', component_property='children'),
    Input(component_id='my-input', component_property='value')
)
def update_output_div(input_value):
    print(Main.eval("2+2"))
    return f'Output: {input_value}'


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

When you interact with the callback you should see : the OSError: exception: access violation reading 0x0000000000000018 error shown in the app

magnusbbc avatar Mar 20 '23 19:03 magnusbbc

Is it possible that Dash may be using multiple threads here? Is Julia eval bring called on a separate thread than the one where Julia was initialized during the callback?

mkitti avatar Mar 20 '23 23:03 mkitti

I also suspected this may be the case, however it seems to me that the default configuration of Dash (as shown in the above example) should only use a single thread

magnusbbc avatar Mar 20 '23 23:03 magnusbbc

I know this is not a great workaround, but have you considered using https://github.com/plotly/Dash.jl

Could you also detail environment system and report your operating system? Did you use pip or conda to set this up?

mkitti avatar Mar 21 '23 05:03 mkitti

Hey, not sure how useful this is for your case but the solution I went with in the end was simply to use HTTP.jl to set up a simple server, and just passed necessary data to and from the Dash app via HTTP requests. I found Dash.jl to be significantly underdeveloped for my requirements.

crabbixOCE avatar Mar 21 '23 06:03 crabbixOCE

I know this is not a great workaround, but have you considered using https://github.com/plotly/Dash.jl

Could you also detail environment system and report your operating system? Did you use pip or conda to set this up?

I am on windows using julia 1.8.5 and python 3.11 (also tried 3.10). I used pip to configure my environment

Like crabbixOCE, i also found Dash.jl to be too underderveloped for me

magnusbbc avatar Mar 21 '23 08:03 magnusbbc

Hey, not sure how useful this is for your case but the solution I went with in the end was simply to use HTTP.jl to set up a simple server, and just passed necessary data to and from the Dash app via HTTP requests. I found Dash.jl to be significantly underdeveloped for my requirements.

Cool! I think that sounds like a decent for now solution. How do you do type conversions? Could you possibly provide a small example?

magnusbbc avatar Mar 21 '23 08:03 magnusbbc

Sure, I would send a json object from the python side, like

q = requests.post(

'http://127.0.0.1:8000/start', json=json.dumps({'data':data_obj}), verify=False, timeout=10 )

And then use the JSON3 package to parse it on the julia side:

const router = HTTP.Router() HTTP.@register(router, "POST", "/start", bar)

HTTP.serve(router, ip"127.0.0.1", 8000)

function bar(req) json_received = JSON3.read(JSON3.read(req.body)) data = json_received["data"]

Don't ask me why the JSON3.read is double-nested, that's just the way it seems to work lmao.

For more complicated structures this might fail; in this case consider using a database or csv files as an intermediate. Hope this helps!

crabbixOCE avatar Mar 21 '23 08:03 crabbixOCE

Has anyone tried the MWE again with Julia v1.9? The new language feature allowing the number of threads to change during execution may help this work. Using juliacall and writing dash callbacks with simple functions like addition worked for me, but I ran into problems with anything involving strings.

lxvm avatar Apr 26 '23 00:04 lxvm