Hi all!
As not-a-developer, I often find myself inserting debugging statements like st.write(some_variable)
throughout my code. This can be suboptimal, so I created a proof-of-concept for a “debug.print” command that allows me to directly print debug information in my Streamlit app
Idea: create a div that which will stick to the bottom and contain debugging info. Include time & line of code from which debug command was triggered. Save history and be able to scroll.
Example: https://stdebug.streamlit.app/
Github: GitHub - TomJohnH/streamlit-debug
Code elements:
- Very simple external module
st_debug.py
- External css style
debug.css
Usage
- Create python file
st_debug.py
(or use the function directely)
import streamlit as st
import datetime
from inspect import getframeinfo, stack
def debug(input):
if "debug_string" not in st.session_state:
st.session_state["debug_string"] = "<b>Debug window ☝️</b>"
now = datetime.datetime.now()
st.session_state["debug_string"] = (
"<div style='border-bottom: dotted; border-width: thin;border-color: #cccccc;'>"
+ str(now.hour)
+ ":"
+ str(now.minute)
+ ":"
+ str(now.second)
+ " Debug.print["
+ str(getframeinfo(stack()[1][0]).lineno)
+ "] "
+ str(input)
+ "</div>"
+ st.session_state["debug_string"]
)
- Create external css file:
.debug {
padding-left: 10px;
position: fixed;
bottom: 0;
left: 0;
right: 0;
max-height: 200px;
background-color: #333;
color: #ccc;
width: 100%;
overflow: auto;
font-family: monospace;
}
- Import module:
import st_debug as d
- Load css:
def local_css(file_name):
with open(file_name) as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
local_css("debug.css")
- At the bottom of your code make additional div:
if "debug_string" in st.session_state:
st.markdown(
f'<div class="debug">{ st.session_state["debug_string"]}</div>',
unsafe_allow_html=True,
)
Write debugging commands:
a = np.matrix("1 2; 3 4")
d.debug("this presents state of the matrix " + str(a))
or
if "counter" not in st.session_state:
st.session_state["counter"] = 1
d.debug("counter " + str(st.session_state["counter"]))
- That’s all Above method is easily reusable in other apps (in fact you have to only import external file, load css and you are ready to go)
BONUS ROUND:
Let’s say that you like the div but you would like to toggle it’s visibility with CTRL + Q
shortcut.
- Expand
st_debug.py
file with function storing js code that will be responsible for div toggle and reaction to key presses:
def js_code():
return """
<script>
function myFunction() {
var x = window.parent.document.getElementById("debug");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function KeyPress(e) {
var evtobj = window.event? event : e
if (evtobj.keyCode == 81 && evtobj.ctrlKey) myFunction();
}
const doc = window.parent.document;
doc.onkeydown = KeyPress;
</script>
"""
- import streamlit.components.v1 in your main app file
import streamlit.components.v1 as components
- Below the “debug div” add js script using
components.html
components.html(
d.js_code(),
height=0,
width=0,
)
Now you can toggle the debug div with CTRL+Q keys combination.
- Happy streamliting!