Reputation: 55
I have a project. I want to use tkinter and selenium. I'm telling a button to enter "https://stackoverflow.com" When I click it it opens but tkinter freezes. How do I get around this?
I am using the code on this site
import tkinter as tk
from selenium import webdriver
# --- functions ---
def on_open():
global driver
if not driver:
driver = webdriver.Chrome()
url = e.get()
driver.get(url)
def on_close():
global driver
if driver:
driver.close()
driver = None
# --- main ---
driver = None
root = tk.Tk()
e = tk.Entry(root)
e.pack()
e.insert('end', 'https://stackoverflow.com')
b = tk.Button(root, text='Selenium Open', command=on_open)
b.pack()
b = tk.Button(root, text='Selenium Close', command=on_close)
b.pack()
root.mainloop()
Upvotes: 1
Views: 393
Reputation: 19979
import threading
from selenium import webdriver
import tkinter as tk
def on_open():
global thread_lock
global driver
global thread
#we use thread_lock to ensure clicking the start button too many times doesn't open many chromedriver instance
#as soon as the code reaches inside this for loop , the thread_lock flag will be set preventing more chromedriver instance creation
#Next chrome driver can be created only after clicking close
if not driver and not thread_lock:
thread_lock = True
options = webdriver.ChromeOptions()
options.page_load_strategy = 'none'
options.add_argument("--window-position=500,500")
driver = webdriver.Chrome(options=options)
url = e.get()
driver.get(url)
def on_close():
global driver
global thread
global thread_lock
#A this flag allows next driver to be created
thread_lock = False
thread.__stop = True
if driver:
driver.quit()
driver = None
# --- main ---
driver = None
root = tk.Tk()
thread_lock = False
e = tk.Entry(root)
e.pack()
e.insert('end', 'https://stackoverflow.com')
thread = None
# you have to create new thread for each click , so wrapping it with a function
def start():
global thread
thread = threading.Thread(
target=on_open, daemon=True)
thread.start()
def kill():
global thread
thread = threading.Thread(
target=on_close, daemon=True)
thread.start()
b = tk.Button(root, text='Selenium Open', command=start)
b.pack()
b = tk.Button(root, text='Selenium Close', command=kill)
b.pack()
root.mainloop()
see the code comments
Upvotes: 2
Reputation: 54743
The UI will be frozen until driver.get(url)
returns. If the fetch takes a long time, your UI will be frozen for a long time. The way around this is to spin that fetch off into a thread, which allows the on_open
function to get back to the event loop.
import threading
def on_open():
global driver
if not driver:
driver = webdriver.Chrome()
url = e.get()
threading.Thread(target=driver.get, args=(url,), daemon=True)
EDIT -- Another one to try.
import threading
def open_chrome( url ):
global driver
driver = webdriver.Chrome()
driver.get( url )
def on_open():
if not driver:
threading.Thread(target=open_chrome, args=(e.get(),), daemon=True)
This might not be the complete answer, either. If "webdriver.Chrome" is actually Python code, then there's nothing you can do. Python only allows one thread at a time to be running Python code. Until that function either waits for something or goes into a C module, the interpreter is tied up.
Upvotes: 3