Streamlit error with columns and st.empty

Summary

New user here! Simple clock & date display in browser

Steps to reproduce

Run this code:

      import streamlit as st
      from time import *
      from datetime import datetime
      
      
      '# Digital Clock Demo using Python & Streamlit'
      '## This is a web app displaying a digital clock and the date today'
      
      pl = st.empty()
      while True:
          now = datetime.now()
          LCDate = str(now.strftime("%A %d %b "))
          HMnow = str(now.strftime("%H:%M:%S"))  # + ":")
      
          with pl.container():
              k1, k2 = st.columns(2)
              # st.metric(' ', LCDate)
              # st.metric(' ', HMnow)
              k1.write(st.metric(' ', LCDate))
              k2.write(st.metric(' ', HMnow))
              sleep(1)
              # pl.empty()

The date should show in Col 1, with constantly updating time on the same line, in column 2

Actual behavior:
Date appears, but no time. Instead error message:

      **StreamlitAPIException**: `_repr_html_()` is not a valid Streamlit command.
      
      Traceback:
      
      ```
      File "/Users/timkendal/Desktop/Python Projects/streamlit_tutorial_series-main/Screenclk_with_Cols.py", line 20, in <module>
          k1.write(st.metric(' ', LCDate))
      ```

Debug info

  • Streamlit version: Streamlit, version 1.16.0

  • Python version: Python 3.8.2

  • Using Conda? PipEnv? PyEnv? Pex? No

  • OS version: MacOS 10.15.7 Catalina

  • Browser version: Chrome 108.0.5359.124

The code above is derived in part from this code, which I found on this site:

        import time
        import streamlit as st
        pl = st.empty()
        secs = 0
        
        while True:
            with pl.container():
                kpi1, kpi2 = st.columns(2)
                kpi1.write(f"{secs} seconds have passed")
                kpi2.write(f"{secs * 2} seconds have passed")
                time.sleep(1)
                secs += 1
                # pl.empty()

which works as expected displaying the updating text in 2 columns in the same line, which is exactly what I’m trying to do.

My code (1st code above) works fine if I remove the columns like this:
It now displays date and time on 2 lines

      import streamlit as st
      from time import *
      from datetime import datetime
      
      
      '# Digital Clock Demo using Python & Streamlit'
      '## This is a web app displaying a digital clock and the date today'
      
      pl = st.empty()
      while True:
          now = datetime.now()
          LCDate = str(now.strftime("%A %d %b "))
          HMnow = str(now.strftime("%H:%M:%S"))  # + ":")
      
          with pl.container():
              # k1, k2 = st.columns(2)
              # st.metric(' ', LCDate)
              # st.metric(' ', HMnow)
              # k1.write(st.metric(' ', LCDate))
              st.metric(' ', LCDate)
              # k2.write(st.metric(' ', HMnow))
              st.metric(' ', HMnow)
              sleep(1)
              # pl.empty()

Any help on explaining the error message and how to avoid it would be greatly appreciated

Thanks in advance

Hi @timk, welcome to the forum!

In this case it’s an easy fix – if you’re using columns like this, you can replace all st.* commands with <column_var>.*. So, st.metric becomes k1.metric, rather than k1.write(st.metric...

In this case you’re trying to write the output of st.metric, which is something that doesn’t work well. So, this version of the code works well.

from datetime import datetime
from time import sleep

import streamlit as st

"# Digital Clock Demo using Python & Streamlit"
"## This is a web app displaying a digital clock and the date today"

pl = st.empty()
while True:
    now = datetime.now()
    LCDate = str(now.strftime("%A %d %b "))
    HMnow = str(now.strftime("%H:%M:%S"))  # + ":")

    with pl.container():
        k1, k2 = st.columns(2)
        k1.metric(" ", LCDate) #CHANGED
        k2.metric(" ", HMnow) # CHANGED
        sleep(1)

Thanks for this prompt and very effective reply - the code now works!

I’m still not quite sure exactly what caused the error though, as the simplification of the code you suggested doesn’t look as though it addresses the error.

But as I say, the code now works, so I’m happy - thanks again and happy new year!

Before you did this

k1.write(st.metric(' ', LCDate))

The fix is to do this instead:

k1.metric(' ', LCDate)

k1.write is just like st.write, and it expects you to pass the object you expect to display. You were passing a metric object to st.write, which Streamlit doesn’t know what to do with. Your code is equivalent to st.write(st.metric(...)), which also won’t work. When working with a column object like k1, you can just take the code that you would normally run with st.<something> and replace it with k1.<something> to instead run that command inside that column.

See st.columns - Streamlit Docs for more details.

Thanks! That’s very clear, and I’m much wiser now - great!

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.