I am having a problem trying to upload the database object using file_uploader and read the tables from the database. I am using SQLite dB for the same.
Below is the sample code:
st.file_uploader does not really upload a file, but loads its content in memory, whereas sqlite3.connect() expects a file path.
A solution is to create a temporary file and give its path to sqlite3.connect().
import streamlit as st
import tempfile
import sqlite3
conn = None
db = st.file_uploader("Upload a SQLite database file.", type="db")
if db:
with tempfile.NamedTemporaryFile() as fp:
fp.write(db.getvalue())
conn = sqlite3.connect(fp.name)
if conn:
# You can use your connection object here...
Here is another version, it creates a temporary file with a random uuid name in the directory from which your have started streamlit. When the connection object is created, it removes the temporary file.
import streamlit as st
import sqlite3
import pathlib
import uuid
conn = None
db = st.file_uploader("Upload a SQLite database file.", type="db")
if db:
fp = pathlib.Path(str(uuid.uuid4()))
# fp = pathlib.Path("/path/to/your/tmpfile")
try:
fp.write_bytes(db.getvalue())
conn = sqlite3.connect(str(fp))
finally:
if fp.is_file():
fp.unlink()
if conn:
st.write("Connection object:", conn)
def main():
st.set_option('deprecation.showfileUploaderEncoding', False)
st.sidebar.write('Bring your database here:')
data = st.sidebar.file_uploader('*Upload or drop the file, maxsize = 1GB:', type = 'odb')
if data:
datos = Loading_file(data)
if st.sidebar.checkbox('Distancia promedio'):
st.success('Loading Distancia promedio')
st.dataframe(datos.dist_prom().style.format({'Distancia': '{:.2f}'}))
if st.sidebar.checkbox('Tiempos de ciclo'):
st.success('Loading tiempos de ciclo:')
st.plotly_chart(datos.cicle_time())
class Loading_file:
def __init__(self,data):
fp = pathlib.Path(str(uuid.uuid4()))
fp.write_bytes(data.getvalue())
self.data = back.Basededatos(str(fp))
The issue here is that nowhere in your code you tell to remove the database.
Your Loading_file class creates a file, but does not delete it in the end.
Here’s how you can fix it (I didn’t test the code though ):
def main():
st.set_option('deprecation.showfileUploaderEncoding', False)
st.sidebar.write('Bring your database here:')
data = st.sidebar.file_uploader('*Upload or drop the file, maxsize = 1GB:', type = 'odb')
if data:
# This `with` statement will call Loading_file.__enter__()
# When your code goes out of this `with` block, Loading_file.__exit__()
# will be automatically called, even if an exception occurs.
with Loading_file(data) as datos:
if st.sidebar.checkbox('Distancia promedio'):
st.success('Loading Distancia promedio')
st.dataframe(datos.dist_prom().style.format({'Distancia': '{:.2f}'}))
if st.sidebar.checkbox('Tiempos de ciclo'):
st.success('Loading tiempos de ciclo:')
st.plotly_chart(datos.cicle_time())
class Loading_file:
def __init__(self, data):
self.bytes = data.getvalue()
self.data = None
self.fp = None
def __enter__(self):
"""Called when entering a `with` block."""
self.fp = pathlib.Path(str(uuid.uuid4()))
self.fp.write_bytes(self.bytes)
self.data = back.Basededatos(str(self.fp))
# We return the current object
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""Run on `with` block exit."""
# Here we just have to remove the temporary database file
self.fp.unlink()
# ... the rest of your methods ...
If you want to learn more about context managers (with statement), you can check out this link:
Hi, I am trying to follow the similar/same approach to read in file and want to get file path. After having file path, I want to pass it to the Subprocess. I was able to see a randomfile name with content same as the input file being created in the directory, but still not getting the file path. Following is my code–basically modify the one above:
@contextmanager
def genome_connect(db_bytes):
fp = Path(str(uuid4()))
fp.write_bytes(db_bytes.getvalue())
conn = str(fp)
try:
yield conn
finally:
conn.close()
fp.unlink()
genome = st.file_uploader("Upload a SQLite database file.", type="gbk")
if genome:
with genome_connect(genome) as conn:
st.write("Connection object:", conn)
For subprocess:
args = ["guidemaker",
"-i",conn,
"-p",pam,
"--guidelength",str(guidelength),
"--strand",strand,
"--lcp",str(lcp),
"--dist",str(dist),
"--outdir","out",
"--log","logfile.txt",
"--threads",str(threads)]
def run_command(args):
"""Run command, transfer stdout/stderr back into Streamlit and manage error"""
#st.info(f"Running '{' '.join(args)}'")
result = subprocess.run(args, capture_output=True, text=True)
try:
result.check_returncode()
#st.info(result.stdout)
st.text(result.stderr)
except subprocess.CalledProcessError as e:
st.error(result.stderr)
raise e