Hello together,
I’m trying to use the subprocess
element of the terminal
widget to run a command with flags and arguments.
Here’s a minimal example:
#!/usr/bin/env python3
import panel as pn
pn.extension("terminal")
term = pn.widgets.Terminal("This is a basic terminal\n\n")
term.write("We will run ls -l\n")
term.subprocess.run("ls", "-l")
term.flush()
term.write("Now we run the next command: ls -l /bin\n")
term.subprocess.run("ls", "-l", "/bin")
pn.Row(term).servable()
The first command works as expected. In the second command, I get:
ValueError: Error. A child process is already running. Cannot start another.
Interesting, if I do this in a class (e.g. for a Pipeline
), I get the same error, and I can then also no longer go back to a previous stage. The following example can be used. The first part is from the previous example, just commenting out the part that does not work:
#!/usr/bin/env python3
import panel as pn
import param
pn.extension("terminal")
term = pn.widgets.Terminal("This is a basic terminal\n\n")
term.write("We will run ls -l\n")
term.subprocess.run("ls", "-l")
# term.flush()
# term.write("Now we run the next command: ls -l /bin\n")
# term.subprocess.run("ls", "-l", "/bin")
class PipelineElement(param.Parameterized):
def panel(self):
return pn.pane.Markdown(f"# {self.__class__.__name__}")
class Stage1(PipelineElement):
def panel(self):
return pn.pane.Markdown("# Stage 1")
class Stage2(PipelineElement):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.term = pn.widgets.Terminal("This is a basic terminal\n\n")
self.run_button = pn.widgets.Button(name="Run", button_type="primary")
self.run_button.on_click(self.run)
def run(self, event):
self.term.write("We will run ls -l\n")
self.term.subprocess.run("ls", "-l")
self.term.flush()
self.term.write("Now we run the next command: ls -l /bin\n")
self.term.subprocess.run("ls", "-l", "/bin")
def panel(self):
return pn.Column(pn.pane.Markdown("# Stage 2"), self.run_button, self.term)
dag = pn.pipeline.Pipeline()
dag.add_stage("Stage1", Stage1)
dag.add_stage("Stage2", Stage2)
dag.define_graph({"Stage1": "Stage2"})
template = pn.template.VanillaTemplate(title="Terminals and Pipeline")
template.main.append(term)
template.main.append(dag)
template.servable()
I’ve tried following the online documentation, but somehow it isn’t working as expected.
The code is also available here as a GitHub Gist.
Any help would be greatly appreciated.
Cheers,
Paul