Rerun incovenience

Hello Community, good day!

I am having a problem which seems to be very common but in my case is making my app not viable. I have an app that uses a same folder CSV file with questions, and among the options, it chooses a X random number of questions and create a mock test. This is for my personal study for a certification on a platform.
The form is working , and I am logging the right answers to evaluate once the user clicks the Submit button.
The problem is being that when the submit is hit, it reruns the script from the top, and recreates the questions (so new ones) and the right answers change, and the evaluation code doesnt work because it compares the old responses with the news right-answers.
I have used the Session-state vars to create a boolean gateway to try to deviate the rerun process FROM the script creation part, but strangely, even with the flag saying the submit is TRUE, and the bool gateway is False, it is passing through the script again.
It seems that the priority is to rerun the script and then continue with the evaluation code.

Does anyone has passed through similar issue?

Many thanks in advance.

The priority is always to first rerun the script, and then do any evaluation: Execution flow - Streamlit Docs

You can use callbacks to first evaluate, and then rerun: Button behavior and examples - Streamlit Docs

But I will use the Callback into the Form Submit button?

Hi Siddhant, follows my code… after the code there is a sample of the questions structure, in the last column I have the right answer.

import pandas as pd
import streamlit as st
import csv
from random import shuffle

#Global initializations
rights = 0
questions_list =
list_responses =
wrong_questions =
right_questions =

if ‘responses’ not in st.session_state:
st.session_state.responses = {}
if ‘form_submitted’ not in st.session_state:
st.session_state.form_submitted = False

st.title(“Archimate Mock Test!”)

with st.form(key=“my_form”, clear_on_submit=True, enter_to_submit=False):
#st.write("Entrando no form= " + str(st.session_state.form_submitted))
if st.session_state.form_submitted == False:
questions_nums = 1
f = open (‘Archimate_Data_Bank.csv’,“r”, encoding=‘UTF8’)
csv_reader = csv.reader(f)
for line in csv_reader:
questions_list.append(line[0])
f.close()
shuffle(questions_list)
newlist = questions_list[:4]
for qt in newlist:
f = open (‘Archimate_Data_Bank.csv’,“r”, encoding=‘UTF8’)
csv_reader = csv.reader(f)
for line in csv_reader:
if line[0]== qt :
st.write(str(questions_nums) + "-- " + line[1])
st.write(line[2])
st.write(line[3])
st.write(line[4])
st.write(line[5])
right_questions.append(line[6])
st.selectbox("Enter response: “,(“A”, “B”, “C”, “D”), key=f"question_{questions_nums}”, index=None)
questions_nums = questions_nums+1
f.close()
submit_button = st.form_submit_button(label=“Submit”)
st.write(right_questions)

if submit_button:
    st.write(st.session_state.form_submitted)
    st.session_state.form_submitted = True
    for i in range(questions_nums-1):
        st.write(i)
        st.session_state.responses[f"question_{i+1}"] = st.session_state[f"question_{i+1}"]
        if st.session_state.responses[f"question_{i+1}"] == right_questions[i]:
            st.warning("Correct!",icon="⚠️")
            rights = rights+1
            list_responses.append(st.session_state.responses[f"question_{i+1}"])
        else:
            st.warning("Incorrect",icon="⚠️")
            wrong_questions.append(i+1)
            list_responses.append(st.session_state.responses[f"question_{i+1}"])
    st.write("Responses:", st.session_state)
    st.write(list_responses)
    for j in range(len(list_responses)):
        st.write ("Question "+ str(j+1) +") " + list_responses[j])
      
    if wrong_questions == []:
        st.write("No wrong answers! Congrats!")
    else:
        st.write ("Wrong Questions:")
        for w in wrong_questions:
            st.write ("Question: "+str(w))
    st.write("Rights: ", rights)
    st.write("len List resp: ", len(list_responses))
    final_score = rights/len(list_responses)*100
    st.write("Your final score is: "+str(final_score)+"%")
st.stop()

1,“ISO/IEC/IEEE defines architecture as the fundamental concepts or properties of a system in its environment embodied in its elements, relationships, and in the principles of its design and evolution.”,A) ISO/IEC/IEEE 42010,B) ISO/IEC/IEEE 15289,C) ISO/IEC/IEEE 12207,D) ISO/IEC/IEEE 29148,A
2,The ArchiMate modeling language was created in the period ______ by the Telematica Instituut.,A) 2000-2002,B) 2002-2004,C) 2004-2006,D) 2006-2008,B
3,Which of the following statement is correct regarding the Architecture Viewpoint?,A) A representation of a system from the perspective of a related set of concerns,B) A specification of the conventions for a particular kind of architecture view,C) A collection of concepts in the context of the ArchiMate language structure,“D) A connection between a source and target concept. Classified as structural, dependency, dynamic, or other”,B
4,Which of the following statement best describes the Stakeholder?,A) Executives of the company,B) All members of the organisation,“C) People who have key roles in, or concerns about the system”,D) A stockholder who owns shares in the organisation,C
5,How many layers of the ArchiMate core language?,A) Two,B) Three,C) Four,D) Five,B

Can you format the entire code as a code block so it is easier to read?

Here you are… :slight_smile:

import pandas as pd
import streamlit as st
import csv
from random import shuffle

#Global initializations
rights = 0
questions_list = []
list_responses = []
wrong_questions = []
right_questions = []

if 'responses' not in st.session_state:
    st.session_state.responses = {}
if 'form_submitted' not in st.session_state:
    st.session_state.form_submitted = False
    
st.title("Archimate Mock Test!")

with st.form(key="my_form", clear_on_submit=True, enter_to_submit=False):
    #st.write("Entrando no form= " + str(st.session_state.form_submitted))
    if st.session_state.form_submitted == False:
        questions_nums = 1
        f = open ('Archimate_Data_Bank.csv',"r", encoding='UTF8')
        csv_reader = csv.reader(f)
        for line in csv_reader:
            questions_list.append(line[0])
        f.close()
        shuffle(questions_list)
        newlist = questions_list[:4]
        for qt in newlist:
            f = open ('Archimate_Data_Bank.csv',"r", encoding='UTF8')
            csv_reader = csv.reader(f)
            for line in csv_reader:
                if line[0]== qt :
                    st.write(str(questions_nums) + "-- " + line[1])
                    st.write(line[2])
                    st.write(line[3])
                    st.write(line[4])
                    st.write(line[5])
                    right_questions.append(line[6])
                    st.selectbox("Enter response: ",("A", "B", "C", "D"), key=f"question_{questions_nums}", index=None)
            questions_nums = questions_nums+1
            f.close()
    submit_button = st.form_submit_button(label="Submit")
    st.write(right_questions)
    
    if submit_button:
        st.write(st.session_state.form_submitted)
        st.session_state.form_submitted = True
        for i in range(questions_nums-1):
            st.write(i)
            st.session_state.responses[f"question_{i+1}"] = st.session_state[f"question_{i+1}"]
            if st.session_state.responses[f"question_{i+1}"] == right_questions[i]:
                st.warning("Correct!",icon="⚠️")
                rights = rights+1
                list_responses.append(st.session_state.responses[f"question_{i+1}"])
            else:
                st.warning("Incorrect",icon="⚠️")
                wrong_questions.append(i+1)
                list_responses.append(st.session_state.responses[f"question_{i+1}"])
        st.write("Responses:", st.session_state)
        st.write(list_responses)
        for j in range(len(list_responses)):
            st.write ("Question "+ str(j+1) +") " + list_responses[j])
          
        if wrong_questions == []:
            st.write("No wrong answers! Congrats!")
        else:
            st.write ("Wrong Questions:")
            for w in wrong_questions:
                st.write ("Question: "+str(w))
        st.write("Rights: ", rights)
        st.write("len List resp: ", len(list_responses))
        final_score = rights/len(list_responses)*100
        st.write("Your final score is: "+str(final_score)+"%")
    st.stop()

Can you also share a sample Archimate_Data_Bank.csv file?
I just need the syntax, not the contents

My idea here is to have the Form construction when the state.form_submitted is False, so when it reruns, I was pressed submit button, and changed the variable to True. But because the rerun comes before the code, the variable will be still False, and it we re-generate the questions and responses again, but with the old user entries… result, the responses will be wrong.

Is there a way to tell Streamlit to run just once? I mean, it runs once and just stop, just like the st.stop() does?

If I use, on_click (callable), what is the precedence between this and the rerun? Which runs first?

Streamlit usually does just this. It runs once, then stops until some event triggers a new rerun.

When you click the button, the callback runs first, then the script reruns.

Hi guys! I was able to fix it, I used the event “on_click” on the form, and changed the flag “form_submitted” to True. The Callback event has precedence over the Rerun, so I made my gateway and when the Rerun happens, I already made all evaluations. The variables were all carried to the Session_State vars.

thanks very much all helps!

1 Like

I don’t know what I was thinking when I said that the form submit button does not support callbacks :see_no_evil:
Maybe I should have had another coffee :coffee:

Glad that you solved it. Looking forward to the app

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