Thanks for sharing your question! It looks like you shared this on StackOverflow as well, and got the following answers:
The question is what kind of user the target is. If it’s another coder, just create a requirements.txt file for your project and give them the source code (i.e. using an online repository like GitHub). Then they can recreate your environments and run the app via Streamlit locally themselves. If the target user is not a coder, you need to package everything, i.e. in a Docker container (see i.e. official documentation here docs.streamlit.io/knowledge-base/tutorials/deploy/docker)
Another option is to package your app as an executable – I recommend checking out this thread.
I don’t believe that answers the OP question; I would like to think that understand the OP question because I have the same exact desire.
I too found the post in Stackoverflow; but for ready access, here is a couple of follow-up questions.
Still within the corporate environment with machines in the same network and the ability to reach each other…is there a simple process for self-hosting?
For as long as upon launching, the streamlit program shows up in the browser in the one machine:
am I supposed to be able to reach the same program from another machine?
is there anything the keeps the program from accepting requests/connections?
is there something easy to configure so that this can be accomplished?
Desktop operating systems usually come with a preinstalled firewall, configured by default to block any incoming connections unless they come from localhost. You might have to configure the firewall to allow an application to listen to incoming requests in a certain port using a certain protocol.
In a corporate environment is common that IT people configure the operating system to comply with the organization policies before handing the computer to users, that are not granted the required permissions to change configurations.
If your operating system was configured by people in your org, those peple can answer your questions better than stranges in the Internet. If not, learn how to configure the firewall.
And no, I don’t know firewall stuff; I am not a web developer, either…that’s why I am using Streamlit …to readily and simply convert a desktop Python program into a web-based one, to explore sharing, etc.
So, I do happen to have some additional privileges in a server box; and, late last night, I found another thread with some brief instructions on how to use docker to launch a streamlit app…it worked; I can now reach my app from any computer.
Another handy way to do this is with ngrok, which allows you to expose a local port to the internet. https://ngrok.com/
e.g.
# in one console window
streamlit run app.py
# In another
ngrok http 8501
Which generates a url that you can share with others to be able to access your app (as long as those commands keep running). It’s not ideal for all scenarios, but I’ve found it handy when just wanting to share something quickly without actually hosting it anywhere.
blackary:
I don’t know about ngrok. I think the OP and I are looking for a self-hosting option and not expose anything outside the company four walls. A brief look at ngrok webpage and it seems like it uses some server in Europe.
Tong
In my previous post, I included a link to the repo with the instructions I followed…they are just a few lines, so, I can include them here:
Go to your working directory
Create a file named Dockerfile, with the following contents:
Copy your streamlit file over and rename it myapp.py, to match reference inside Dockerfile
Build: docker build -t myapp1:latest
Run: docker run -d -p 8501:8501 --name=testgui myapp1:latest
Go to browser and use app
Stop: docker stop testgui
Remove container: docker rm testgui
Remove image: docker rmi myapp1:latest
Oops…post-edit: You need the requirements.txt file, too.
So, like I said, the above steps kind of worked for me in that I was able to run the program in one machine and connect to it from another BUT, it only works once…for the first user to connect to it…what’s up with that?
Is this issue normal?
What else does not need to do for the app to work for multiple users?
then, when at a terminal prompt, after I type docker run ..., I do not get the prompt back
which is the same thing that happens if you type: streamlit run <myapp>.py, when working locally, anyway; so,
I was not quite surprised about that
What surprises me is that even though supposedly there is some kind of web-server running, it is not able to handle more than one user; in other words, after I launch docker run... for the first time, the program only works for the one user that connects first; if a second user wants to use the program, it does not work correctly for them.
And so, in as much as I did not like the ngrok proposal, I speculate that the solution may be along those lines, i.e., some kind of additional web-server that can launch different instances of the app got subsequent users? Here is where I don’t know what I am talking about because I am not a web-developer.
FWIW, I just did what seemed to me the simplest thing that could possibly work and it actually worked.
Launched a streamlit app in a device (endeavourOS without any special network configuration)
Sent the link to the app url (let’s say http://192.168.0.10:8501) to a couple of other devices connected to the same local network (android)
Open the link in each of the other devices.
This worked for me and I guess it should work in most domestic networks. As I said before, it may or may not work in your corporate network / with corporate devices, depending on corporate policies and how they are implemented.
Hi, Goyo…thanks for nothing Your answer is as good as “It works for me” and it does not help…would you mind showing the precise steps you followed in that “simplest thing that could possibly work”? I really doubt that it is a network issue, it seems more of a web server issue.
By the way, I was reading the Panel docs and, interestingly enough, they mention something interesting in relation to allowing different users having their own instance of the app while visiting the same web page…something about wrapping the final Python app back into a function. Panel uses the Bokeh server.
I enumerated the steps 1, 2 and 3. Let me know whatever you don’t understand. It is as simple as it looks. Launch the app in a computer (streamlit run app.py), look at the “Network URL” that appears in the terminal, go to another computer, open a browser and point it to the aforementioned “Network URL”, that’s all. I used two clients simultaneously because you said it only worked for one in your setup, so I wanted to test that.
I am not saying you are having network issues, that I don’t know. You were using docker and I barely know anything about it so I won’t even speculate about what went wrong. It was just a warning that network issues can happen.
I don’t know about your issue about not handling multiple users, but the simplest case that @Goyo is describing is: launch your app locally the same way you always do: streamlit run my_app.py. There really aren’t any special instruction here.
Observe two things when you launch your app locally.
The terminal will report two links to your running app. One via local host and one via your ip.
The window that automatically opens up is using the localhost version. The localhost url will not work on another computer. The ip version will (provided the other computer is on the same local network and any involved firewalls allow it, etc.).
My own network is pretty locked down so I hadn’t bothered to check if anything special needed to be done to offer up the app to the network. Thanks @Goyo for doing a test.
If you can open up your app on two different tab simultaneously locally, then the app is not having an issue with multiple users. Each tab is a separate session. If accessing the app from a different computer using the ip address link causes a limit on connections, I would suspect it is a network configuration issue.
Thank you both for clarifying things up, checking and double checking.
I tested and re-tested a couple of permutations,
from two different machines
with two different users
and even
just one user, in one machine (locahost itself) and two browser tabs
And it was pretty consistent…no matter user nor machine:
the first tab to upload the input file succeeds
the second tab to upload the input file fails
So, I went back to the source code and noticed a couple of things in play.
the function validating the input file has the @cache decorator
I am using a session state variable to track whether the input file passed validation
The skeleton code looks as follows:
import streamlit as st
st.session_state.inpfile_checked = False
@st.cache
def inpfile_validate():
.
.
.
if good:
st.session_state.inpfile_checked = True
else:
st.session_state.inpfile_checked = False
inpfile = st.file_uploader("Input file", type='csv', key='inpfile')
inpfile_validate()
if st.session_state.inpfile_checked:
pass
else:
st.write('Error: Unacceptable file name.')
So, this is what I am seeing:
the first tab to upload the input file triggers the execution of inpfile_validate(), which succeeds
the first tab also triggers the caching of inpfile_validate()
by the time the second tab uploads the input file, the validate function is not executed because I am using the same exact input file; and, so, the session_state variable is left False
So, I believe this is telling me that:
the session_state variable is NOT being shared between tabs
the cached function IS being shared between tabs
After writing the last few lines above, I went ahead and tested with two different input file names; in this case, both tabs work.
A cache only caches the final output and no action within. Furthermore, it caches relative to its inputs, so you’d need to pass it the data of the file so it can cache the correct validation status for different files.
import streamlit as st
st.session_state.inpfile_checked = False
@st.cache
def inpfile_validate(uploaded_file):
.
# run check on locally defined uploaded_file variable
.
if good:
return True
else:
return False
inpfile = st.file_uploader("Input file", type='csv', key='inpfile')
st.session_state.inpfile_checked = inpfile_validate(inpfile)
if st.session_state.inpfile_checked:
pass
else:
st.write('Error: Unacceptable file name.')
Note, I didn’t run a test with the st.cache to see if it correctly identifies files as “the same” as you’d want. Since the file uploader returns an UploadedFile object which is a subclass of BytesIO, I am guessing it will perform as desired. Just a caveat that I didn’t validate that point with testing.
“This happens because the Streamlit cache is global to all users. So everyone contributes to everyone else’s performance.”
Between the above statement and what you and the docs mention regarding caching of inputs and outputs, one also needs to make sure that the function does not have any side effects. In my case, the side effect was changing the value of a global variable without it being an input nor an output…this side effect does not happen after the function has been cached.
Thanks alot for your solution. I have a question if you may . I want to change the network url to something more neat like www.myapp.com . Can you share with me some resources to do so?
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.