import gradio as gr import requests import time import datetime import threading # Function to fetch cryptocurrency prices from CoinGecko def get_crypto_prices(crypto_ids, vs_currency="usd"): try: ids = ",".join(crypto_ids) url = f"https://api.coingecko.com/api/v3/simple/price?ids={ids}&vs_currencies={vs_currency}" response = requests.get(url) response.raise_for_status() data = response.json() prices = {} for crypto_id in crypto_ids: if crypto_id in data: prices[crypto_id] = data[crypto_id][vs_currency] else: prices[crypto_id] = "N/A" # Indicate if price is not available return prices except requests.exceptions.RequestException as e: return {crypto_id: f"Error: {e}" for crypto_id in crypto_ids} except Exception as e: return {crypto_id: f"Error: {e}" for crypto_id in crypto_ids} # Function to get the current time as a string def get_current_time(): now = datetime.datetime.now() return now.strftime("%Y-%m-%d %H:%M:%S") # Function to calculate the countdown to the next minute def get_countdown(): now = datetime.datetime.now() seconds_to_next_minute = 60 - now.second return f"Next Update in: {seconds_to_next_minute} seconds" # Shared data (prices) shared_prices = {} # This is the "Prices" that is shown to the GUI. def scheduled_update(): # schedule a thread to trigger every minute. global shared_prices # import the global shared prices so we can apply changes. crypto_ids = ["bitcoin", "ethereum", "binancecoin", "ripple", "litecoin", "dash"] shared_prices = get_crypto_prices(crypto_ids) # Apply the new prices now = datetime.datetime.now() seconds_to_next_minute = 60 - now.second # get correct timing, it triggers in 1 minute. threading.Timer(seconds_to_next_minute, scheduled_update).start() # Schedule the next update # Gradio Interface def update_all(): # runs the GUI clock. global shared_prices crypto_ids = ["bitcoin", "ethereum", "binancecoin", "ripple", "litecoin", "dash"] # we want it as one function. price_strings = [] for crypto_id in crypto_ids: if crypto_id not in shared_prices: # when it loads the price might not be there, show some error message instead, make it more user friendy. price_strings.append("Loading, Please wait.") # give a warning state that something is going on. continue price = shared_prices[crypto_id] # it might come as error if isinstance(price, str): # means an error string. price_strings.append(f"Current {crypto_id.upper()} Price: {price}") else: price_strings.append(f"Current {crypto_id.upper()} Price: ${price:.2f}") # apply it to the UI. return get_current_time(), get_countdown(), *price_strings with gr.Blocks() as demo: clock_output = gr.Textbox(label="Current Time") # put it before the row. countdown_output = gr.Textbox(label="Next Update") with gr.Row(): # prices are in these objects now. with gr.Column(): output_btc = gr.Textbox(label="BTC Price") output_eth = gr.Textbox(label="ETH Price") output_bnb = gr.Textbox(label="BNB Price") with gr.Column(): output_xrp = gr.Textbox(label="XRP Price") output_ltc = gr.Textbox(label="LTC Price") output_dash = gr.Textbox(label="DASH Price") demo.load(update_all, None, [clock_output, countdown_output, output_btc, output_eth, output_bnb, output_xrp, output_ltc, output_dash], every=1) # Update clock every second, the timer runs every second. Might be bad, as it updates more frequent. # Start the scheduled updates and fetch the initial data now = datetime.datetime.now() # so it can run for a bit before setting. seconds_to_next_minute = 60 - now.second time.sleep(seconds_to_next_minute) # wait for start, you may want to do this to display what you want in the GUI so you can debug. scheduled_update() # start it, get new results if __name__ == "__main__": demo.launch()