The last time I needed that 'non-blocking' wait in tkinter was in a simple MusicApp. To avoid blocking the tkinter mainloop() I have to run the code in chunks. As I use pexpect I can't run the code in an other thread and using .after/.after_cancel to schedule the 'chunks' execution. As Bryan Oakley suggested I'm using .wait_variable(). Here's the code:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''"Basically, all I want to do is wait until the user presses a
Tkinter button (labeled 'Press me'), and then after that start the
rest of the code (everyting represented by print('run the code...')".
Custom code is represented by RUN_CNT function. UPDATE_MSG is to
visualize that functionality. Non-blocking wait is done by tkinter
wait_variable() function
'''
import tkinter as tk
RUN, DONE, TERMINATED = 0, 1, 2
class App(tk.Tk):
def __init__(self):
super().__init__()
self.cnt = 100
self.msg = tk.Label(self, text='{:5d}'.format(self.cnt))
self.msg.pack()
self.var = tk.IntVar()
self.var.set(RUN)
self.id = None
tk.Button(self, text='Start', command=self.run_cnt).pack()
self.btn = tk.Button(self, text='Press me', state='disabled',
command=lambda: self.var.set(DONE))
self.btn.pack()
self.protocol('WM_DELETE_WINDOW', self.quit)
def quit(self):
# w/o the following WM_DELETE_WINDOW never ends the app
self.var.set(TERMINATED)
self.unsked()
super().quit()
def update_msg(self):
'''Run the user code in chunks
to give the mainloop() the chance to handle events'''
if 0 < self.cnt:
self.msg.configure(text='{:5d}'.format(self.cnt))
self.cnt -= 2
else:
self.var.set(DONE)
self.sked()
def unsked(self):
if self.id:
self.after_cancel(self.id)
self.id = None
def sked(self, func=None):
self.unsked()
self.id = self.after(200, func if func else self.update_msg)
def run_cnt(self):
self.sked(self.update_msg)
self.btn.configure(state='normal')
self.wait_variable(self.var)
if self.var.get() == DONE:
print("Yay you pressed a button!")
else:
print('Terminated')
self.quit()
if __name__ == '__main__':
App().mainloop()
run_cnt(), and update_msg() represent the 'custom' code. update_msg() updates the tk.Label to visually confirm the functionality. 'Press me' button indicates the event we're waiting for.

Tested for Python 3.9.2, Debian GNU/Linux 11 (bullseye)
It prints:
$ python tkwait.py
Yay you pressed a button!
$ python tkwait.py
Terminated