PyUtilib / pyutilib

A collection of general Python utilities, including logging and file IO, subprocess management, plugin systems, and workflow management.
BSD 3-Clause "New" or "Revised" License
34 stars 20 forks source link

pyutilib.subprocess.run in dash #115

Closed rhshadrach closed 3 years ago

rhshadrach commented 3 years ago

Attempting to run Pyomo in dash, I see the following stack trace (I've removed the top half of the stack):

[snip]/python3.7/site-packages/pyomo/opt/solver/shellcmd.py", line 308, in _execute_command
    define_signal_handlers = self._define_signal_handlers
[snip]/python3.7/site-packages/pyutilib/subprocess/processmngr.py", line 552, in run_command
    = signal.signal(signal.SIGHUP, handler)
[snip]/python3.7/signal.py", line 47, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread

I can reproduce by calling pyutilib.subprocess.run directly. Here is a minimal example:

import dash
from dash.dependencies import Input, Output
import dash_html_components as html
from pyutilib.subprocess import run

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),
    html.Button('Use pyutilib.subprocess.run()', id='my_button'),
    html.Div(id='my_output')
])

@app.callback(
    Output('my_output', 'children'),
    Input('my_button', 'n_clicks'),
    prevent_initial_call=True)
def my_function(_):
    run("ls")
    return html.H3('It Worked!')

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

Is this something that can be supported?

jsiirola commented 3 years ago

See #31: you can disable the signal handling logic in pyutilib.subprocess with:

import pyutilib.subprocess.GlobalData
pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT = False