0

I have Python code that includes a Tkinter GUI and several asynchronous functions. However, when I run the code, only either the GUI or the functions are running. In this case the GUI starts first, and the functions only run after the window is closed. Here is the code segment:

# Workers ########################################################################################################

async def process_orders():
    last_incomplete_orders = []
    while True:
        # Logic for order processing here
        #print(colored("Processing orders...")
        # Get orders that haven't been fulfilled yet
        incomplete_orders = await get_incomplete_orders()
        
        if incomplete_orders != last_incomplete_orders:
            incomplete_order_ids = []
            for payment in incomplete_orders:
                ID, Name, Progress = payment
                incomplete_order_ids.append(ID)
            #print(colored(f'{datetime.datetime.now().strftime("%H:%M:%S")} - IDs of incomplete orders: {str(incomplete_order_ids)[1:-1]}', 'magenta', 'on_white'))
            last_incomplete_orders = incomplete_orders
            
        await asyncio.sleep(5)

async def process_payments():
    last_unconfirmed_payments = []
    while True:
        # Payment processing
        #print(colored("Processing payments...")

        # Get payments that haven't been confirmed yet
        unconfirmed_payments = await get_pending_payment_requests()
        if unconfirmed_payments != last_unconfirmed_payments:
            printpaymentids = []
            for payment in unconfirmed_payments:
                payment_id, client_id, btc_adress, amt_btc, amt_eur, status = payment
                printpaymentids.append(payment_id)
            #print(colored(f'{datetime.datetime.now().strftime("%H:%M:%S")} - IDs of unpaid payment requests: {str(printpaymentids)[1:-1]}', 'magenta', 'on_cyan'))
            last_unconfirmed_payments = unconfirmed_payments
        for payment in unconfirmed_payments:
            payment_id, client_id, btc_adress, amt_btc, amt_eur, status = payment
            is_confirmed = False 
            is_confirmed = await is_payment_confirmed(payment_id)
            if is_confirmed:
                await release_order(payment_id) 

        await asyncio.sleep(2)  


async def main():
    await clear_all_tables()
    await asyncio.sleep(5)
    task1 = asyncio.create_task(process_orders())
    task2 = asyncio.create_task(process_payments())
    task3 = asyncio.create_task(funfunc())
    task4 = asyncio.create_task(run_gui())
    #task5 = asyncio.create_task(test_product_flow())
    #task6 = asyncio.create_task(test_product_flow())
    #task7 = asyncio.create_task(test_product_flow())
    #task8 = asyncio.create_task(test_product_flow())
    #task9 = asyncio.create_task(test_product_flow())
    #task10 = asyncio.create_task(test_product_flow())

    # Wait for all tasks to complete
    await asyncio.gather(task1, task2, task3, task4)#, task5, task6, task7, task8, task9, task10)


async def funfunc():
    await asyncio.sleep(90)
    messagebox.showinfo('Daily Report', str(await sum_daily_income()))
    
async def run_gui():
    # Create the application window
    window = c.CTk()
    window.title("Simple GUI")
    window.geometry("300x200")

    # Create a label
    label = c.CTkLabel(window, text="Hello, World!")
    label.pack()

    # Create a button
    button = c.CTkButton(window, text="Click me!", command=on_button_click)
    button.pack()
    window.mainloop()


async def create_test_customer():
    await asyncio.sleep(random.randint(1,30))
    await create_client(random.randint(100000,999999), ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(8)))

async def test_product_flow():
    # Create Order
    await asyncio.sleep(random.randint(0,30))
    order_id = await create_order(''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(50)), 100, 'test')
    
    # Create PaymentRequest
    payment_id = await create_payment_request(order_id, 1, 'testbtcadress1827635t123', random.randint(50,1000))
    
    # Confirm or Reject PaymentRequest
    await asyncio.sleep(random.randint(0,30))
    if random.randint(0,1) == 1:
        await confirm_payment(payment_id)
        await asyncio.sleep(random.randint(0,30))
        # Fulfill Order
        await simulate_fulfilled_order(order_id)
    else:
        await reject_payment(payment_id)
        
loop = asyncio.run(main())

I tried making the GUI as a class and the async functions as class methods but still wouldn't work for me.

UPDATE: I managed to solve it using the threading library and creating a seperate Thread for the GUI and for the Asynchronous functions. Thanks for the help guys!

Fabian
  • 11
  • 3
  • Generally you'll want to run any blocking functions in their own thread(s) so as not to block the tkinter event loop (freezing your GUI), though I'm less confident on how to do this with async functions. Also, there doesn't appear to be any tkinter code here - it would help if you could include the relevant GUI code as well. – JRiggles May 16 '23 at 15:49
  • @JRiggles. Tkinter code is in the run_gui() function. window.mainloop() was missing, but still does not work. You suggest running seperate threads for GUI and the main program? – Fabian May 16 '23 at 19:26
  • Ah, I missed `run_gui` - apologies! And yes, that's what I'm suggesting. Generally you'd run your GUI code in the main thread and any long running / blocking functions in their own thread(s) – JRiggles May 16 '23 at 19:29
  • A better way with a lower GUI latency and a lower CPU usage is to use the Trio guest mode. See [Trio reference](https://trio.readthedocs.io/en/stable/reference-lowlevel.html#using-guest-mode-to-run-trio-on-top-of-other-event-loops) and [this example](https://github.com/richardsheridan/trio-guest/blob/master/trio_guest_tkinter.py). – relent95 May 18 '23 at 17:18
  • @relent95 Oh yea thanks! I used threading and it worked perfectly! – Fabian May 18 '23 at 20:35

0 Answers0