Закрытие приложения в фоновом режиме на PyQt5 + Selenium
Столкнулся с проблемой с закрытием приложения после принудительного закрытия браузера. После этого, если закрыть окно приложения, то оно продолжает работать в фоновом режиме.
Пробовал использовать разные методы, кнопку создавал даже отдельную - ничего не помогло. Сами методы:
def threadexit(self):
t1 = Thread(target=self.exit)
t1.start()
def exit(self):
QApplication.processEvents()
def threadexit(self):
t1 = Thread(target=self.exit)
t1.start()
def exit(self):
QApplication.exit()
self.btnExit.clicked.connect(self.close)
Так же в функции с selenium есть time.sleep(3600). Предполагаю, что именно из-за этого программа на mac os работает в фоновом режиме.
И собственно сам вопрос: как можно закрыть программу так, чтобы она не работала в фоновом режиме? И если это из-за функции задержки, то как ее можно заменить?
Собственно функциональная часть кода:
def thread1(self):
t1 = Thread(target=self.start)
t1.start()
def save(self):
proxy = self.LineProxy.text()
lproxy = self.LineLProxy.text()
pproxy = self.LinePProxy.text()
loginru = self.LineRuLogin.text()
passwordru = self.LineRuPassword.text()
if proxy == '':
pass
else:
with open('logpas.txt', 'w+') as f:
f.write(proxy)
f.write('\n')
f.write(lproxy)
f.write('\n')
f.write(pproxy)
f.write('\n')
f.write(loginru)
f.write('\n')
f.write(passwordru)
def start(self):
proxy = self.LineProxy.text()
lproxy = self.LineLProxy.text()
pproxy = self.LineProxy.text()
loginru = self.LineRuLogin.text()
passwordru = self.LineRuPassword.text()
with open('logpas.txt', 'r+') as f:
a = f.read().split('\n')[0:5]
q = []
for i in range(len(a)):
b = a[i]
q.append(b)
if proxy != q[0] and proxy != lproxy:
url = 'https://rutracker.org/'
options = webdriver.ChromeOptions()
options.add_argument(f'--proxy-server={proxy}')
driver = webdriver.Chrome(executable_path='chromedriver.exe', options=options)
driver.get(url)
driver.implicitly_wait(10)
keyboard.write(lproxy)
keyboard.send('tab')
driver.implicitly_wait(10)
keyboard.write(pproxy)
keyboard.send('enter')
vhod = driver.find_element(By.LINK_TEXT, 'Вход').click()
login = driver.find_element(By.ID, 'top-login-uname')
login.send_keys(loginru)
password = driver.find_element(By.ID, 'top-login-pwd')
password.send_keys(passwordru)
password.send_keys(Keys.ENTER)
time.sleep(3600)
driver.quit()
elif q[0] == '':
pass
else:
url = 'https://rutracker.org/'
options = webdriver.ChromeOptions()
options.add_argument(f'--proxy-server={q[0]}')
driver = webdriver.Chrome(executable_path='chromedriver.exe', options=options)
driver.get(url)
driver.implicitly_wait(10)
keyboard.write(q[1])
keyboard.send('tab')
driver.implicitly_wait(10)
keyboard.write(q[2])
keyboard.send('enter')
vhod = driver.find_element(By.LINK_TEXT, 'Вход').click()
login = driver.find_element(By.ID, 'top-login-uname')
login.send_keys(q[3])
password = driver.find_element(By.ID, 'top-login-pwd')
password.send_keys(q[4])
password.send_keys(Keys.ENTER)
time.sleep(3600)
driver.quit()
Ответы (1 шт):
Основная проблема в time.sleep(3600), поток спит и закроется только когда проснется. Поэтому большую задержку разбиваем на кучу мелких с проверкой закрыто ли окно браузера. Мне понравилось предложение Federico Rubbi, в котором следят за log журналом драйвера - когда там появиться сообщение о закрытии браузера. Пример работы сделал на tkinter, но я думаю особого труда не составит перенести на pyqt5. Основу программы взял отсюда.
import time
import threading
import tkinter as tk
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# Создаем окно с кнопкой.
class App(tk.Tk):
def __init__(self):
super().__init__()
self.button = tk.Button(self, command=self.start_action, text="Запуск selenium")
self.button.pack(padx=50, pady=50)
self.driver = None
self.check = None
self.flag = False
# Запускаем дополнительный поток для selenium.
def start_action(self):
self.button.config(state=tk.DISABLED)
thread = threading.Thread(target=self.run_selenium)
thread.start()
self.check_thread(thread)
# Делаем активной кнопку только после завершения потока
def check_thread(self, thread):
if thread.is_alive():
self.check = self.after(500, lambda: self.check_thread(thread))
else:
self.button.config(state=tk.NORMAL)
def run_selenium(self):
print("Запуск selenium...")
url = r"https://ya.ru/"
self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
self.driver.set_window_position(500, 100)
self.driver.set_window_size(800, 600)
self.driver.get(url)
self.flag = True
time.sleep(3)
print("Закройте окно браузера")
# Запускаем "ручной" сон с периодической - два раза в секунду - проверкой не закрыто ли окно браузера
time_stop = 10 # 3600
time_start = time.time()
while self.flag:
time.sleep(0.5)
if time.time() - time_start < time_stop:
if self.driver.get_log('driver'):
print(self.driver.get_log('driver'))
if self.driver.get_log('driver')[-1][
'message'] == "Unable to evaluate script: no such window: target window already closed\nfrom unknown error: web view not found\n":
self.driver.quit()
self.flag = False
print("Браузер закрыт пользователем!")
else:
self.driver.quit()
self.flag = False
print("Действие selenium завершено, без воздействия потусторонних сил!")
if __name__ == "__main__":
app = App()
app.mainloop()
Если при появлении в терминале надписи "Закройте окно браузера" вы закроете окно, то поток завершится не дожидаясь окончания заданного времени, а если подождете 10(3600) секунд, то процесс завершиться по времени.