Stop or Cancel button

Is there any mechanism is to cancel or stop a running process using a button? in my application, I want to start a process and then stop it using another button. I tried so many ways but couldn’t make it work.

import streamlit as st
import time
from SessionState import get
from multiprocessing import Process

st.sidebar.title("controls")
start = st.sidebar.button("start")
stop = st.sidebar.button("stop")


session_state = get(a=0)


def working():
    print("working started")
    session_state.a = 2
    for i in range(100):
        time.sleep(1)
        print(session_state.a)
        if session_state.a == 1:
            break

p = Process(target=working)
global pid
if start:
    print("start")
    p.start()
    pid = p.pid
    print("in start", pid)

if stop:
    print("stop")
    session_state.a = 1
    print("in stop", pid)

1 Like

Welcome to the forum, @rohola_zandie :wave:

I believe the code below does what you want:

from multiprocessing import Process
import streamlit as st
import SessionState
import time
import os
import signal

st.sidebar.title("Controls")
start = st.sidebar.button("Start")
stop = st.sidebar.button("Stop")

state = SessionState.get(pid=None)


def job():
    for _ in range(100):
        print("In progress")
        time.sleep(1)


if start:
    p = Process(target=job)
    p.start()
    state.pid = p.pid
    st.write("Started process with pid:", state.pid)

if stop:
    os.kill(state.pid, signal.SIGKILL)
    st.write("Stopped process with pid:", state.pid)
    state.pid = None

I’ve changed it a little bit, but the main idea is that you need to store the pid in the session state and only start a new process inside the start if condition.

Please let me know if you need any further clarification.

2 Likes

Thanks it’s working!

My pleasure!

1 Like

Hi,
This solution only works in linux but in windows I get this error.

ctx None
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\multiprocessing\spawn.py", line 105, in spawn_main
exitcode = _main(fd)
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\multiprocessing\spawn.py", line 114, in _main
prepare(preparation_data)
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\multiprocessing\spawn.py", line 225, in prepare
_fixup_main_from_path(data['init_main_from_path'])
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\multiprocessing\spawn.py", line 277, in _fixup_main_from_path
run_name="mp_main")
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\runpy.py", line 263, in run_path
pkg_name=pkg_name, script_name=fname)
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
  File "F:\codes\python\kiha_app\work_with_stop.py", line 15, in <module>
state = SessionState.get(pid=None)
  File "F:\codes\python\kiha_app\SessionState.py", line 69, in get
current_server = Server.get_current()
  File "c:\users\mohsen\anaconda3\envs\tf_gpu\lib\site-packages\streamlit\server\Server.py", line 165, in get_current
raise RuntimeError("Server has not been initialized yet")
RuntimeError: Server has not been initialized yet

You could solve that detecting the OS from platform and sending the correct signal but it’s easier with psutil:

from multiprocessing import Process
import streamlit as st
import SessionState
import time
import psutil

st.sidebar.title("Controls")
start = st.sidebar.button("Start")
stop = st.sidebar.button("Stop")

state = SessionState.get(pid=None)


def job():
    for _ in range(100):
        print("In progress")
        time.sleep(1)


if start:
    p = Process(target=job)
    p.start()
    state.pid = p.pid
    st.write("Started process with pid:", state.pid)

if stop:
    p = psutil.Process(state.pid)
    p.terminate()
    st.write("Stopped process with pid:", state.pid)
    state.pid = None