I’m creating a multipage app where pages are dynamically created then navigated to with page_switch
but Streamlit refuses to navigate to the page, saying it does not yet exist despite Python signaling the page exists and its content has finished being written. There seems to be a buffer between when a page is ready to be read by Python versus displayed with Streamlit. Is there a way to signal when Streamlit is ready to display the page to avoid errors?
Here’s the error Streamlit displays when creating a page called Star Wars
:
FileNotFoundError: [Errno 2] No such file or directory: 'pages/StarWars.py'
Traceback:
File "/usr/local/lib/python3.12/site-packages/streamlit/runtime/scriptrunner/exec_code.py", line 88, in exec_func_with_error_handling
result = func()
^^^^^^
File "/usr/local/lib/python3.12/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 579, in code_to_exec
exec(code, module.__dict__)
File "/app/app.py", line 133, in <module>
main()
File "/app/app.py", line 130, in main
create_new_page(query)
File "/app/app.py", line 92, in create_new_page
Path(file_path).touch()
File "/usr/local/lib/python3.12/pathlib.py", line 1303, in touch
fd = os.open(self, flags, mode)
^^^^^^^^^^^^^^^^^^^^^^^^^^
Here’s my current approach to the problem –focusing on file size stabilization– which doesn’t work. The page_template function with its arguments returns Python code for a Streamlit page:
# Create new file & write the page content to the file
Path(file_path).touch()
with open(file_path, "w") as file:
page_content = get_template(title=page_title, search_query=search_query)
file.write(page_content)
# Wait until the file is populated
start_time = time.time()
last_size = -1
while True:
# Check if the file exists
if os.path.exists(file_path):
# Get the current file size
current_size = os.path.getsize(file_path)
# If size hasn't changed for two consecutive checks, assume it's ready
if current_size == last_size:
st.switch_page(file_path)
last_size = current_size
else:
# File doesn't exist yet, continue waiting
pass
# Timeout handling
if time.time() - start_time > 30:
raise TimeoutError(f"Request Timeout: File {file_path} did not stabilize within 30 seconds. Try again.")
time.sleep(0.1)
Locally, I’ve gotten around this by adding a time.sleep() for 3 seconds after the file size has stabilized (not ideal and very scrappy) but in production this fails and I get the original error. Anything less than a 3 second wait is spotty at best and fails most of the time. This error affects all newly created pages.
Has anyone encountered similar race conditions when creating and navigating to dynamically generated pages? Any suggestions would be super helpful. Happy to share more of my code too. Thanks everyone