Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.99/89: Рейтинг темы: голосов - 89, средняя оценка - 4.99
Эксперт Python
 Аватар для АмигоСП
295 / 108 / 57
Регистрация: 07.12.2016
Сообщений: 209

Обновление главного окна в PyQt5

07.12.2016, 15:50. Показов 19435. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго Всем времени суток. Наверное уже не раз создавались подобные темы, но ответа на свой вопрос так и не нашел( Поэтому спрошу еще раз, уж извиняйте. Вообщем имеется прога на питоне(3.5.2) По сути брут-перебиралка. На указанном сайте проверяет логины(зарегистрирован такой или нет). Делает она это через прокси, естественно. В консольной версии отрабатывает на ура и без проблем. В оконной же версии(через PyQt 5.6) прога отрабатывает свой цикл, но при этом главное окно “зависает”. Что мы делаем в главном окне: Выбираем файл с прокси(он добавляется в очередь Queue). Выбираем файл с логинами(он тоже добавляется в очередь Queue, но уже в другую). Выставляем кол-во потоков(модуль threading), задаём таймаут соединения(модуль grab), выбираем тип прокси(http/socks), указываем куда сохранить результат. Далее запускаем обработку в несколько потоков через threading. Во время обработки, если прокси сервер не срабатывает(через try - except), то логин снова добавляется в очередь. Если прокси в очереди закончились, то файл открывается заного и создаётся снова очередь с прокси. И так, пока не закончатся все логины. 'Хорошие логины' добавляются в список и потом отдельной функцией записываются в файл(результат, который указали при выборе сохранения). В инете встречаются примеры через QThread, либо QObject. Но все они для PyQt4. Хотелось бы понять вообще принцип - какие именно данные засовывать в QThread, либо QObject. Надо ли использовать питоновский модуль threading или все реализовывать через QTread. Вообщем смысл - чтобы главное окно не зависало(оно отображает еще промежуточную информацию через лейблы - сколько чего проверилось)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
07.12.2016, 15:50
Ответы с готовыми решениями:

Дублирование главного окна при открытии нового окна
У меня есть основное окно типа QWidget, при нажатии на кнопку открывается окно типа QDialog. Но вместе с диалоговым окном открывается и...

PyQt5 При запуске окна из другого окна, методы класса не работают
Не знаю, как грамотно объяснить свою проблему, но предполагаю, что она точно в открытии нового окна по нажатию кнопки в другом окне. ...

Как мне сослаться на вторичные окна (формы) из главного окна
Мне скинули код.....я пытаюсь коды этих отдельных форм просмотреть в конструкторе.......то есть создав новый проект.......но наткнувшись на...

38
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
07.12.2016, 16:53
Очень много написал. Теперь давай к сути. Ты хочешь узнать как в отдельном потоке выполнять парсинг, чтобы не зависало окно программы, так?
0
Эксперт Python
 Аватар для АмигоСП
295 / 108 / 57
Регистрация: 07.12.2016
Сообщений: 209
07.12.2016, 16:58  [ТС]
Да, всё правильно. И еще бы хотелось понять(на моём примере) - что именно засовывать в этот отдельный поток. А то по PyQt5 что то не так уж много информации с примерами, а заказанная книга придет только к концу декабря) Новичек в этом деле. Только начал питона изучать
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
07.12.2016, 17:30
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import sys
import time
import threading
 
from PyQt5 import QtCore, QtWidgets
 
 
def thread(my_func):
    """
    Запускает функцию в отдельном потоке
    """
    def wrapper(*args, **kwargs):
        my_thread = threading.Thread(target=my_func, args=args, kwargs=kwargs)
        my_thread.start()
    return wrapper
 
@thread
def processing(signal):
    """
    Эмулирует обработку (скачивание) каких-то данных
    """
    res = [i for i in 'hello']
    time.sleep(5)
    signal.emit(res)  # Посылаем сигнал в котором передаём полученные данные
 
 
class MyWidget(QtWidgets.QWidget):
    my_signal = QtCore.pyqtSignal(list, name='my_signal')
 
    def __init__(self, parent=None):
        super(MyWidget, self).__init__(parent)
        self.mainLayout = QtWidgets.QHBoxLayout()
        self.setLayout(self.mainLayout)
 
        self.button = QtWidgets.QPushButton("Emit your signal!", self)
        self.mainLayout.addWidget(self.button)
 
        # При нажатии на кнопку запускаем обработку данных
        self.button.clicked.connect(lambda: processing(self.my_signal))
 
        # Обработчик сигнала
        self.my_signal.connect(self.mySignalHandler, QtCore.Qt.QueuedConnection)
 
    def mySignalHandler(self, data):  # Вызывается для обработки сигнала
        print(data)
 
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MyWidget()
    window.show()
    app.exec_()
Цитата Сообщение от АмигоСП Посмотреть сообщение
что именно засовывать в этот отдельный поток
Скачивание данные
1
Эксперт Python
 Аватар для АмигоСП
295 / 108 / 57
Регистрация: 07.12.2016
Сообщений: 209
07.12.2016, 18:56  [ТС]
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
    def authication(self):                            #Основная функция, из за которой зависает главное окно
        while not self.Email.empty():
            emailFull = self.Email.get()         # Получаем из очереди Queue Логины
            if not self.Proxy.empty():
                proxyFull = self.Proxy.get()     # Получаем из очереди Queue прокси(дальше идет проверка очереди и обновление
            elif self.checkReloadProxy != self.checkReloadMax:
                self.getFileProxy()
                proxyFull = self.Proxy.get()
                self.checkReloadProxy += 1
                self.label_7.setText("Proxy Обновился : " + str(self.checkReloadProxy) + '/' + str(self.checkReloadMax) + 'раз(а)')
            else:
                self.openFileProxy()
                #print('Загрузите новый файл м ПРОКСИ')
                self.findingError()
                proxyFull = self.Proxy.get()
                self.checkReloadProxy = 0
 
            auth = Grab()
            param = {
                'input': emailFull[:emailFull.find(':')]
            }
            proxies = proxyFull[:-1]
            auth.setup(post=param, proxy=proxies, proxy_type=self.proxyType, connect_timeout=self.TIME_LIMIT)
            try:
                auth.go(self.BaseURL)  # Здесь посылаем запрос с параметрами на нужный адрес
                #print(auth.url)
                AUTH = auth.response.unicode_body()
                self.emailRES.put((AUTH, emailFull))    #Если прокси сработал, то засовываем данные для дальнейшего парсинга в очередь
                self.label_13.setText("Проверено Email(ов) : " + str(self.Email.qsize()) + '/' + str(self.valueemail))
                self.progressCount += self.forProgress    # Это для прогрессбара в главном окне
                self.progressBar.setValue(self.progressCount)
 
            except Exception: # Если прокси не сработал, то используем счетчик и передаем информацию главному окну через лейбл_6
                self.errorProxy += 1
                self.label_6.setText("Неудача Proxy : " + str(self.errorProxy))
            
                self.Email.put(emailFull) # Добавляем логин заного в очередь
 
 
            self.label_4.setText('Осталось Proxy : ' + str(self.Proxy.qsize()) + '/' + str(self.valueproxy))
            self.Email.task_done()
            self.Proxy.task_done()
 
    def main(self): # На мейне законекчена кнопка старт - собираем все данные и запускаем потоки через treading
        self.getProxyType()
        self.TIME_LIMIT = self.timeOUTvalue.value()
        self.checkReloadMax = self.spinBox.value()
        VALUE_THREAD = self.thread_value.value()    #Практически все данные берутся из виджетов главного окна
 
        for _ in range(VALUE_THREAD):
            _ = threading.Thread(target=self.authication)
            _.start()
 
        self.Email.join()
        self.findingError() #В эту функцию передаются "сработавшие через прокси" логины для парсинга и в ней же записываются в файл
        self.emailRES.join()
        #self.file.close()
        self.progressBar.setValue(100)
        wdg = QMessageBox(self)
        wdg.setText('Обработка Завершена')
        wdg.exec_()
alex925, Большое Вам спасибо, что откликнулись. Если я правильно понял, то потоки мне нужно будет запускать из декоратора (def tread() - который вы указали в своем примере) и в него передавать информацию о кол-вах потоков. А декоратор мне применять целиком к своей функции (def authication(self))? Или создавать новую функцию и засовывать в неё только тот код, который начинается с посыла запроса уже по указанному адресу?
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
07.12.2016, 19:34
Цитата Сообщение от АмигоСП Посмотреть сообщение
Если я правильно понял, то потоки мне нужно будет запускать из декоратора
Не из декоратора. Декоратором надо оборачивать функции, которые нужно запустить в отельных потоках.

И ещё в потоках не должно происходить манипулирование gui. Гуём управлять можно только из главного потока.
0
Эксперт Python
 Аватар для АмигоСП
295 / 108 / 57
Регистрация: 07.12.2016
Сообщений: 209
07.12.2016, 19:51  [ТС]
Чего то я окончательно запутался((. В главном окне я нажимаю кнопку "Старт" и запускается функция main, которая в свою очередь запускает в несколько потоков функцию authication. Что же мне тогда оборачивать декоратором?
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
07.12.2016, 20:17
АмигоСП, весь твой код надо переписывать, он написан не правильно. У тебя смешано представление и логика. Их нужно разделять. Весь gui (это view), должен быть отделен от логики (твой парсер) и взаимодейстовать они должны с помощью слотов и сигналов, так как у тебя парсер будет работать в отдельном потоке.
0
Эксперт Python
 Аватар для АмигоСП
295 / 108 / 57
Регистрация: 07.12.2016
Сообщений: 209
07.12.2016, 22:21  [ТС]
alex925, еще раз спасибо за советы и ответы) А то изучаю самостоятельно только полтора месяца питон. До этого вообще не программировал. Скажи, а так правильней будет писать: Создать 2 класса. Один класс это гуи, а второй сам парсер. Из гуи передавать в парсер только настройки(пути к файлам из QFileDialog, таймауты, кол-во потоков..вообщем все, что выставляется через виджеты в главном окне. А парсер получается передаёт в гуи только информацию для лейблов и прогрессбара? И еще какую литературу неплохо почитать по PyQt5? На данный момент заказал книгу Python 3 и PyQt 5. Разработка приложений.(Прохоренок Н., Дронов В.)
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
08.12.2016, 07:33
Цитата Сообщение от АмигоСП Посмотреть сообщение
Создать 2 класса. Один класс это гуи, а второй сам парсер
Не обязательно.
Ну окно скорее всего получится в виде 1 класса и там все поместиться, а парсер скорее всего удобнее сделать в функциональном стиле (но это все зависит от конкретной ситуации).
0
Эксперт Python
 Аватар для АмигоСП
295 / 108 / 57
Регистрация: 07.12.2016
Сообщений: 209
08.12.2016, 18:57  [ТС]
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from PyQt5.QtWidgets import QWidget, QFileDialog
from PyQt5.QtCore import pyqtSignal
from queue import Queue
 
Proxy = Queue()
 
def getFileProxy(pathProxy):
    openProxy = open(pathProxy, 'r')
    for proxy in openProxy:
        Proxy.put(proxy)
    valueproxy = Proxy.qsize()
    label9 = 'Proxy в файле : ' + str(valueproxy)
    '''
    Здесь хотелось бы передать данные для главного окна(Кол-во проксей в файле)
    и установить их в лавном окне через label.setText()
    '''
    openProxy.close()
 
class MyWindow(QWidget, PROXY.Ui_Form):
    my_signal = pyqtSignal(str, int)
 
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.openFileProxy)
 
    def openFileProxy(self):
        opnProxyFile = QFileDialog.getOpenFileName(self, 'Выбрать файл с PROXY', filter='Text Files(*.txt);;All Files(*)')[0]
        self.label_1.setText('OK')
        '''
        Здесь хотелось бы передать данные в(путь к файлу из opnProxyFile в функцию getFileProxy)
        '''
        self.label_2.setText('Proxy в файле : ' + str(self.valueproxy))
alex925, а можно еще вас попросить? Вот в этом примере как через pyqtSignal, connect и emit передавать данные? Из главного окна передать путь к файлу в стороннюю функцию. А после обработки, из сторонней функции передать данные(кол-во проксей в файле) обратно в главное окно и обновить label
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
08.12.2016, 19:52
АмигоСП, все это же есть в моем первом примере, с чем там не разобрался?
0
Эксперт Python
 Аватар для АмигоСП
295 / 108 / 57
Регистрация: 07.12.2016
Сообщений: 209
08.12.2016, 20:03  [ТС]
Да чего то совсем туплю видимо(. У тебя в примере кнопка коннектится к исполняемой функции и передаёт сигнал(который по сути имеет возможности pyqtSignal). А у меня получается при нажатии на кнопку сначало вызывается QfileDialog и я в нём выбираю нужный файл(создаётся путь к этому файлу) .Вот его мне надо передать в стороннюю функцию. А от сторонней функции в ответе получить str(с колличеством проксей в файле) и обновить в главном окне label. Или мне нужно передать pyqtSignal(path) и в него вложить путь? А в сторонней функции уже эмитить?
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
08.12.2016, 20:35
АмигоСП, просто вторым аргументом передавай и все
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
08.12.2016, 20:47
Используйте процессы, а не потоки(или комбинируйте) это будет лучше.
Т.е 1-процесс-с-GUI + N-рабочих-процессов
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
08.12.2016, 21:07
Цитата Сообщение от Avazart Посмотреть сообщение
Т.е 1-процесс-с-GUI + N-рабочих-процессов
Тогда уж 1 процесс под гуй, а второй под потоки, но это ооочень усложнит все взаимодействие, тем более для новичка. Лучше уж асинхронку юзать, оно получится производительней 2 предыдущих вариантов, но опять же не легко правда.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
08.12.2016, 21:18
А нафига потоки? Если потоки в питоне не дают выигрыша?
Асинхронка не будет производительнее, ибо как я понял тут не только работа с сетью.

Хотя я использую в своем парсере асинхронный QNetworkAccessManager без потоков и процессов, но у меня нет такой нагрузки и проксей да и парсинг довольно простой.
0
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
08.12.2016, 21:26
Цитата Сообщение от Avazart Посмотреть сообщение
Асинхронка не будет производительнее, ибо как я понял тут не только работа с сетью.
На сколько я понял ему только с сетью работать надо. Отбирать правильные пароли и нет, так что выйгрышь будет и существенный, а при работе с процессами много уйдет на накладные расходы.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
08.12.2016, 21:30
Цитата Сообщение от alex925 Посмотреть сообщение
На сколько я понял ему только с сетью работать надо. Отбирать правильные пароли и нет, так что выйгрышь будет и существенный, а при работе с процессами много уйдет на накладные расходы.
Ну тогда можно использовать QNetworkAccessManager там по моему внутри до 7 соединений одновременно поддерживается.
1
2742 / 2341 / 620
Регистрация: 19.03.2012
Сообщений: 8,830
08.12.2016, 21:39
Не знал, интересная информация. То есть он по сути сам асинхронно выполняет запросы?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.12.2016, 21:39
Помогаю со студенческими работами здесь

Как узнать margin-left любого элемента от главного окна окна браузера?
причем не важно какую вложенность имеет элемент сам элемент, т.е. в скольких контейнерах он бы не находился, нужно найти его marginLeft от...

Где и как правильно перерисовывать дочерние окна при изменении главного окна ?
Где и как правильно перерисовывать дочерние окна при изменении главного окна ? Про WM_SIZE знаю. Про остальное только догадываюсь.

Запуск второго окна перед стартом главного окна
необходимо запустить второе окно до старта основного окна и вызвать основное окно после завершения второго окна

Позиционирование дочернего окна относительно элемента главного окна
Всем привет. Подскажите пожалуйста, как можно сделать. У меня есть главное окно, на котором условно говоря расположен textbox, также у меня...

Переход из окна главного меню на другие окна приложения
Дали задание для курсового проекта Написать приложение на C# для Windows предназначенное для разгадывания ребусов у меня возникло три...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru