Sequence of execution

I am having again problems with the hidden async/multithreading nature of streamlit. I just started to work on a new local app that interfaces a hardware component (power supply). In the example below it is absolutely necessary that the dps functions are atomic and do not mix in their execution. The while loop runs fine. However, if I press the button, the dps.reset_statistics() function causes errors. By changing the sleep time in the while loop I can verify that this only happens if press the button when the dps.output() function is about to execute. Reducing the sleep time, causes the errors to appear always. This tells me that streamlit interrupts the button triggered function by the dps.output() function which then causes the communication with the instrument to fail. Any ideas what to do? This is with version 1.42. I did similar things in the past but dont remember this kind of problems. I am using this simple modbus script that does not do any threading/async things: minimalmodbus/minimalmodbus.py at master · pyhys/minimalmodbus · GitHub

import streamlit as st
import sk120
import time

session = st.session_state

if 'init' not in session: # init section
    session.init = True

@st.cache_resource
def init():
    ser = sk120.Serial_modbus('/dev/ttyUSB1', 1, 115200, 8)
    dps = sk120.sk120(ser)	
    return dps

dps = init()

if st.button('reset statistics'):    
    dps.reset_statistics()

pos1 = st.empty()

while True :
    pos1.write(dps.output())
    time.sleep(2)

Solved the problem which was actually different than I initially thought! The problem was not one function interrupting another but the restart of the script once the button was pressed. If the script was restarted (by pressing the button) when the hardware command sequence was in progress and thus could not complete, the error occured. By using the new st.fragment method, I can prevent this like so (just showing the changed code for the loop and the button):

pos1 = st.empty()

@st.fragment(run_every=0.1)
def live():
    if session.cmd == 1:dps.reset_statistics()  
    else : pos1.write(dps.output())
    session.cmd = 0

@st.fragment
def reset():
    if st.button('reset statistics'): session.cmd = 1

reset()
live()
1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.