Hello Team,
I have few doubts about page switching in streamlit and it is not working per my understanding.
My dir structure:
$HOME / login.py
$HOME / pages / app1.py app2.py app3.py
I am launching the main app (login.py) as streamlit run login.py (on default port 8501)
It presents the user with login form.
After validation of user and password, I am switching to app1.py
if login == ‘success’:
st.switch_page(‘pages/app1.py’)
app1.py gets loaded but the all pages(including login.py) are shown in sidebar navigation pane.
To hide the login page I have used the st-pages package(show_pages) to show only required pages in app1.py
app1.py:
from st_pages import show_pages, Page
…
show_pages([Page(‘pages/app1.py’), Page(‘pages/app2.py’), Page(‘pages/app3.py’)])
However, now If I launch another tab (localhost:8501) in the browser, I am taken directly to app1.py page instead of taking me to login page.
I suppose this is because of page switching.
So basically, If I don’t hide pages using show_pages in app1.py, on launching another tab (localhost:8501), I get to see login page everytime, but after successful login, I still see this login.py page in sidebar.
If I hide pages in app1.py to just show what I want, on launching a new tab I am taken directly to app1.py without the login form.
What I would like is on successful login only app1, app2 and app3 should be shown for navigation, but everytime I launch the a new tab on 8501 port, it should present me with login form.
This is important from users’ perspective because the users of my app should be presented with login page everytime and not for 1st time only, because right now only 1st user gets the login page and subsequent users are directly taken to app1 page.
Versions:
streamlit=1.30
python=3.11
Please let me know if more information is required.
Thanks.
Hello,
Thanks for your reply.
Presently, I am just checking in database whether the said user is present.
To illustrate further, I am attaching screenshots.
As can be seen the user gets to see all pages in sidebar.
Case 2 (pages are hidden via show_pages() )
a. User login form (Same as Case 1 → a)
b. User logs in:
Note that the login page is now hidden in sidebar.
The only code change (app1.py) is the show_pages() method .
app1.py
st_pages.show_pages([Page(“pages/app1.py”), Page(“pages/app2.py”), Page(“pages/app3.py”)])
Please let me know if you need more info.
Is the show_pages() method causing this behavior or is it something else.
I checked the doc for show_pages() but didn’t get any info on this.
Also, if you have any docs on how to deploy such login based apps of switching/selective loading of pages, kindly let me know.
Thanks.
Hello,
Thanks for your reply.
Yes, I think hide_pages() with empty list does the trick. Thank you for your solution.
However, just for my understanding I put show_pages([Page(“pages/app1.py”), Page(“pages/app2.py”), Page(“pages/app3.py”)]) in pages/app1.py but that didn’t work. In fact it showed all the pages. However, hide_pages([“login”]) works and hides the login page. I think I didn’t quite understand what show_pages() does ? Also, noticed that show_pages() takes a list of Pages while hide_pages() takes a list of strings(filenames) and that too without .py extension.
Can you share a link to your repo, show the full folder structure? It appears they you’re running app.py, but I don’t know where pages/page1.py is. Did you create a folder called pages and a file called page1.py in that folder? And is the folder pages in the same folder as app.py?
I just popped over to a Windows computer to play around. Interestingly, I’m observing that st.switch_page breaks when it’s in a try-except block but not when it’s outside.
import streamlit as st
try:
if st.button("pages/app2.py"):
st.switch_page("pages/app2.py")
st.page_link("pages/app2.py")
except:
st.subheader("`dir/file.py` didn't work")
if st.button("pages/app2.py outside try"):
st.switch_page("pages/app2.py")
st.page_link("pages/app2.py")
st.page_link works in both blocks, even if the order is reversed. st.switch_page works in the block without try-except, but not the other inside try. This holds true if the blocks are reversed in order.
(I’m building a larger test script, but this just seemed like a weird observation while I was fiddling…)
Hello,
I have a similar use case, but st.switch_page() works if it is in else block of try.
E.g. code:
import streamlit as st
query_results = Get Data from Database
try:
next(query_results)
except StopIteration:
st.error(“No data”)
else:
st.switch_page(“pages/page1.py”)
We believe we have a fix to the switch_page. We have noticed in Windows that the auto complete of streamlit run app.py is actually appending a ./ to it. So streamlit run .\app.py. This has been causing the issues we can confirm, and we plan to release a patch with this fix.
Can you double verify how you are running the streamlit app and confirm this is the problem?
If it’s still an issue, I would love to get some more logs. I wrote a streamlit script to give us more information (using our internal APIs). If you can run this where the page variable is set and the exception you see occurs, I would appreciate it.
import os
import streamlit as st
from streamlit import source_util
from streamlit.runtime.scriptrunner import get_script_run_ctx
page = "pages/page_two.py" # MODIFY TO YOUR PAGE
ctx = get_script_run_ctx()
ctx_main_script = ""
if ctx:
ctx_main_script = ctx.main_script_path
st.write("**Main Script File**")
st.text(f"\"{ctx_main_script}\"")
st.write("**Current Working Directory**")
st.text(f"\"{os.getcwd()}\"")
st.write("**Normalized Current Working Directory**")
st.text(f"\"{os.path.normpath(os.getcwd())}\"")
st.write("**Main Script Path**")
main_script_path = os.path.join(os.getcwd(), ctx_main_script)
st.text(f"\"{main_script_path}\"")
st.write("**Main Script Directory**")
main_script_directory = os.path.dirname(main_script_path)
st.text(f"\"{main_script_directory}\"")
st.write("**Normalized Path**")
page = os.path.normpath(page)
st.text(f"\"{page}\"")
st.write("**Requested Page**")
requested_page = os.path.join(main_script_directory, page)
st.text(f"\"{requested_page}\"")
st.write("**All Pages Page**")
all_app_pages = list(source_util.get_pages(ctx_main_script).values())
st.json(all_app_pages, expanded=True)
st.page_link(page, label="Page Two")
I can tell from the output that streamlit is being run via streamlit run .\app.py
This is supplying the .\ to the path, and you can see for the Requested Page, we have E:\multi_page\.\pages\page2.py with the erroneous .\ in the middle. This is creating confusion.
So I have two pieces of good news.
You can fix this now by ensuring the .\ is not included. So you would need to ensure streamlit run app.py without the .\. Hopefully, the code should work.
We are releasing a patch to avoid this issue in the first place. We have found especially on windows, the .\ is added via autocomplete, and we should be more flexible.
Let me know if the (1) solves your issue, but if not, we should have 1.31.1 shortly to verify.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.