Latest posts on PyQt5 QThread периодическое соединение с БД в отдельном потоке topichttps://python.su/forum/topic/38049/2019-11-21T00:59:57+02:00Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-21T00:59:57+02:00py.user.next205649Видимо, тут какая-то ошибка архитектуры Qt. В результате появилось два способа порождать потоки и куча разговоров о том, как всё же правильно это делать.<br/><br/>Девчонка эта пишет, что до своей публикации она <u>ничего не нашла в документации</u> по Qt, кроме способа через run(). Остальные пишут, что постоянно сталкиваются со странными проблемами при многопоточной разработке через run(). И тут она выявляет своим умом правильный способ, решающий все проблемы, и публикует его. Тут же все подтверждают, что их проблемы решились этим способом. А дальше откуда-то <u>в документации Qt появляется</u> этот её способ.<br/><br/>И теперь там типа два способа существует, кучи разговоров ведутся и типа так и должно быть. <img src="/static/djangobb_forum/img/smilies/wink.png" /><br/><br/><br/>tags: pyqt thread
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-20T15:05:15+02:00Rodegast205638> Т.е. наследование от QThread не то чтобы совсем неправильно, но приводит к ненужному смешиванию разных наборов функций в одном классе, что ухудшает читаемость и поддерживаемость кода.<br/><br/>Вот что бы этого не происходило нужно следовать принципу “единой ответственности”. Т.е. в наследнике от QThread должен содержаться код который будет работать только в отдельном потоке, а всё остальное должно быть вынесено из этого класса.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-20T14:31:02+02:00PEHDOM205634<blockquote><em>Rodegast</em><br/>Чем же тебе метод run() не нравится?</blockquote>ну есть мнение что "Класс QThread создан и предназначен для использования в качестве интерфейса к потокам операционной системы, но не для того, чтобы помещать в него код, предназначенный для выполнения в отдельном потоке. В ООП мы наследуем класс для того чтобы расширить или углубить функциональность базового класса. Единственное оправдание для наследования QThread, которое я могу представить, это добавление такой функциональности, которой в QThread не существует, например, передача указателя на область памяти, которую поток может использовать для своего стека, или, возможно, добавление поддержки интерфейсов реального времени. Загрузка файлов, работа с базами данных, и подобные функции не должны присутствовать в наследуемых классах QThread; они должны реализовываться в других объектах» <br/>источник <a href="https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong">https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong</a><br/>Т.е. наследование от QThread не то чтобы совсем неправильно, но приводит к ненужному смешиванию разных наборов функций в одном классе, что ухудшает читаемость и поддерживаемость кода.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-20T13:37:37+02:00Rodegast205631> там один парень обнаружил, что эти действия, описанные в производном классе, выполняются в том же потоке, где объект производного класса QThread был создан, а не в новом потоке<br/><br/>Это и так понятно. То что находится или вызывается из run выполняется в дочернем потоке, а то что вызывается из основного будут выполнены в основном.<br/><br/>> И из-за этого появляются зависания, так как действия другого потока происходят не в другом потоке, а в этом же потоке - в главном потоке.<br/><br/>Конечно, если не верно проектировать многопоточное приложение, то так и будет.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-20T13:07:23+02:00py.user.next205628<blockquote><em>Rodegast</em><br/>Чем же тебе метод run() не нравится?</blockquote><a href="https://doc.qt.io/qt-5/qthread.html#details">https://doc.qt.io/qt-5/qthread.html#details</a><br/><blockquote>It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). This means that all of QThread's queued slots and invoked methods will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.</blockquote><br/>Если почитаешь комменты у той бабы, там один парень обнаружил, что эти действия, описанные в производном классе, выполняются в том же потоке, где объект производного класса QThread был создан, а не в новом потоке. И из-за этого появляются зависания, так как действия другого потока происходят не в другом потоке, а в этом же потоке - в главном потоке.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-20T11:12:53+02:00Rodegast205626> всё работает и метод run() не нужен.<br/><br/>Чем же тебе метод run() не нравится?
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-20T07:49:55+02:00py.user.next205604<blockquote><em>Rodegast</em><br/>Да хватит уже повторять бред этой бабы!</blockquote>Хорошая девочка - провела расследование. Хоть какую-то пользу принесла мировому сообществу. Прекрасный подход, где всё работает и <u>метод run() не нужен</u>.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-19T20:18:33+02:00Rodegast205591> Здесь приводил пример использования QThread с отсылкой на бабу.<br/><br/>Да хватит уже повторять бред этой бабы!<br/><br/>> что у вас передается вторым аргументом? откуда вы взяли вообще такой синтаксис?<br/><br/>Это норм. он флаги для соединения передаёт, обычно они не нужны но иногда бывают полезными.<br/><br/>> Таки у небезизвестных граждан Прохорёнка и Дронова подсмотрен сей код был.<br/><br/>Не читай его книгу, там на 90% тупой перевод документации.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-19T09:53:48+02:00PEHDOM205578<blockquote><em>cyberaxe77</em><br/>Таки у небезизвестных граждан Прохорёнка и Дронова подсмотрен сей код был.</blockquote>хорошо, давайте я поставлю вопрос по другому, зачем вам там Qt.QueuedConnection? чем оно отличается от дефолтного Qt.AutoConnection? Если вы чтото пишете вы должны отдавать себе отчет за что отвечает каждая комманда.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-18T17:09:51+02:00cyberaxe77205553<blockquote><em>PEHDOM</em><br/>что у вас передается вторым аргументом? откуда вы взяли вообще такой синтаксис?</blockquote>Таки у небезизвестных граждан Прохорёнка и Дронова подсмотрен сей код был.<br/>
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-18T17:07:04+02:00cyberaxe77205552Спасибо всем помогающим мне.<br/>Вот “пофиксил”… <br/>Как <strike>тебе такое, Илон Маск</strike> вам такой “фикс”, уважаемые знатоки?<img src="/static/djangobb_forum/img/smilies/smile.png" /><br/><div class="code"><pre> <span class="ch">#!/usr/bin/python3</span>
<span class="c1"># -*- coding:utf-8 -*-</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">UI_MainForm</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtWidgets</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtGui</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtCore</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtSql</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">class</span> <span class="nc">MyThread</span><span class="p">(</span><span class="n">QThread</span><span class="p">):</span>
<span class="n">mysignal</span> <span class="o">=</span> <span class="n">pyqtSignal</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_user</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">_passwd</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">user</span> <span class="o">=</span> <span class="n">_user</span>
<span class="bp">self</span><span class="o">.</span><span class="n">passwd</span> <span class="o">=</span> <span class="n">_passwd</span>
<span class="n">QThread</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parent</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">QSqlDatabase</span><span class="o">.</span><span class="n">addDatabase</span><span class="p">(</span><span class="s1">'QMYSQL'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setHostName</span><span class="p">(</span><span class="s1">'localhost'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setDatabaseName</span><span class="p">(</span><span class="s1">'testbase'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setUserName</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">user</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setPassword</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">passwd</span><span class="p">)</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">open</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ok</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mysignal</span><span class="o">.</span><span class="n">emit</span><span class="p">(</span><span class="s1">'Ok'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'Debug: Connection: Ok'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mysignal</span><span class="o">.</span><span class="n">emit</span><span class="p">(</span><span class="s1">'Failed'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'Debug: Connection: Failed '</span> <span class="o">+</span> <span class="n">db</span><span class="o">.</span><span class="n">lastError</span><span class="p">()</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="k">class</span> <span class="nc">MainForm</span><span class="p">(</span><span class="n">QMainWindow</span><span class="p">,</span> <span class="n">UI_MainForm</span><span class="o">.</span><span class="n">Ui_MainWindow</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">QMainWindow</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">setupUi</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_quit</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">qApp</span><span class="o">.</span><span class="n">quit</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">connect_db</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_disconnect</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">disconnect_db</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">start_thread</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">connect_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">QSqlDatabase</span><span class="o">.</span><span class="n">addDatabase</span><span class="p">(</span><span class="s1">'QMYSQL'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setHostName</span><span class="p">(</span><span class="s1">'localhost'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setDatabaseName</span><span class="p">(</span><span class="s1">'testbase'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setUserName</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="n">db</span><span class="o">.</span><span class="n">setPassword</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">open</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ok</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_connection_status</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="s1">'Connection status: Ok'</span><span class="p">)</span>
<span class="n">QMessageBox</span><span class="o">.</span><span class="n">information</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'Information'</span><span class="p">,</span> <span class="s1">'Successful database connection'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_connection_status</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="s1">'Connection status: Failed'</span><span class="p">)</span>
<span class="n">QMessageBox</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'ERROR!'</span><span class="p">,</span> <span class="s1">'No database connection!'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">disconnect_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">setFocus</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">change_label_conn_status</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_connection_status</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="s1">'Connection status: '</span> <span class="o">+</span> <span class="n">s</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">start_thread</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mythread</span> <span class="o">=</span> <span class="n">MyThread</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">text</span><span class="p">(),</span> <span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mythread</span><span class="o">.</span><span class="n">mysignal</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">change_label_conn_status</span><span class="p">,</span> <span class="n">Qt</span><span class="o">.</span><span class="n">QueuedConnection</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mythread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">QApplication</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span>
<span class="n">win</span> <span class="o">=</span> <span class="n">MainForm</span><span class="p">()</span>
<span class="n">win</span><span class="o">.</span><span class="n">show</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">exec_</span><span class="p">())</span>
</pre></div>
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-18T14:33:53+02:00PEHDOM205539<blockquote><em>cyberaxe77</em><br/>1. При дауне MySql, label_connection_status не изменяется на “failed”, хотя в консоль метод run() гадит print('Debug: Connection: Failed ' + db.lastError().text()), как и было задумано. Почему?</blockquote>эм-м-м- а что это у вас <br/><div class="code"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">mythread</span><span class="o">.</span><span class="n">mysignal</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">change_label_conn_status</span><span class="p">,</span> <span class="n">Qt</span><span class="o">.</span><span class="n">QueuedConnection</span><span class="p">)</span>
</pre></div>что у вас передается вторым аргументом? откуда вы взяли вообще такой синтаксис?<br/><blockquote><em>cyberaxe77</em><br/>2. Два потока (в конструкторе и в методе start_thread) - бред. Как избавиться от этого бреда? Как сделать правильно?</blockquote>очевидно вынести передачу логина-пароля из конструктора като так:<br/><div class="code"><pre> <span class="k">class</span> <span class="nc">MyThread</span><span class="p">(</span><span class="n">QThread</span><span class="p">):</span>
<span class="n">mysignal</span> <span class="o">=</span> <span class="n">pyqtSignal</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">setAuth</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">passwd</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_user</span> <span class="o">=</span> <span class="n">user</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_passwd</span> <span class="o">=</span> <span class="n">passwd</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">....</span>
<span class="n">db</span><span class="o">.</span><span class="n">setUserName</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_user</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setPassword</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_passwd</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>в принципе , наверно это можно и в run() сделать<br/>ЗЫ Есть мнение что переопрелять метод run некошерно и не соответвует парадигме ООП а нужно делать как показал <strong>py.user.next</strong> в посте выше.<br/>Учитывая что “ решил побаловаться с потоками в PyQt5. Придумал небольшую учебную задачку” то вам должно быть небезинтересно.<br/><br/><br/><blockquote><em>cyberaxe77</em><br/>3. Может быть можно как-то иначе реализовать проверку доступности MySql для соединения?</blockquote>Ну самый простой способ это смотреть открыт ли соответсвующий порт, правда при этом вы не знаете какая именно программа слушает этот порт и работает ли она, а так , кроме как попытаться установить соединение пока никакого иного способа не придумали.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-18T14:11:19+02:00py.user.next205535<a href="https://python.su/forum/post/196618/">Здесь</a> приводил пример использования QThread с отсылкой на бабу.
Общий :: GUI :: PyQt5 QThread периодическое соединение с БД в отдельном потоке
2019-11-18T11:33:52+02:00cyberaxe77205529Здравствуйте форумчане.<br/>Собственно решил побаловаться с потоками в PyQt5. Придумал небольшую учебную задачку для себя по данной теме.<br/>Форма авторизации для MySql. Всё стандартно: user - password в QLineEdit, кнопки “connect”, “disconnect” и QLabel сообщающая о статусе соединения. Форма должна проверять возможность соединения с сервером 1 раз в 3 секунды. Для этого я в метод run() класса QThread поместил соединение с БД.<br/><div class="code"><pre> <span class="ch">#!/usr/bin/python3</span>
<span class="c1"># -*- coding:utf-8 -*-</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">UI_MainForm</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtWidgets</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtGui</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtCore</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">PyQt5.QtSql</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">class</span> <span class="nc">MyThread</span><span class="p">(</span><span class="n">QThread</span><span class="p">):</span>
<span class="n">mysignal</span> <span class="o">=</span> <span class="n">pyqtSignal</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_user</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">_passwd</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">user</span> <span class="o">=</span> <span class="n">_user</span>
<span class="bp">self</span><span class="o">.</span><span class="n">passwd</span> <span class="o">=</span> <span class="n">_passwd</span>
<span class="n">QThread</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parent</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">QSqlDatabase</span><span class="o">.</span><span class="n">addDatabase</span><span class="p">(</span><span class="s1">'QMYSQL'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setHostName</span><span class="p">(</span><span class="s1">'localhost'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setDatabaseName</span><span class="p">(</span><span class="s1">'testbase'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setUserName</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">user</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setPassword</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">passwd</span><span class="p">)</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">open</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ok</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mysignal</span><span class="o">.</span><span class="n">emit</span><span class="p">(</span><span class="s1">'ok'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'Debug: Connection: Ok'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mysignal</span><span class="o">.</span><span class="n">emit</span><span class="p">(</span><span class="s1">'failed'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'Debug: Connection: Failed '</span> <span class="o">+</span> <span class="n">db</span><span class="o">.</span><span class="n">lastError</span><span class="p">()</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="k">class</span> <span class="nc">MainForm</span><span class="p">(</span><span class="n">QMainWindow</span><span class="p">,</span> <span class="n">UI_MainForm</span><span class="o">.</span><span class="n">Ui_MainWindow</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">QMainWindow</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">setupUi</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mythread</span> <span class="o">=</span> <span class="n">MyThread</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_quit</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">qApp</span><span class="o">.</span><span class="n">quit</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">connect_db</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_disconnect</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">disconnect_db</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">clicked</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">start_thread</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mythread</span><span class="o">.</span><span class="n">mysignal</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">change_label_conn_status</span><span class="p">,</span> <span class="n">Qt</span><span class="o">.</span><span class="n">QueuedConnection</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">connect_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">QSqlDatabase</span><span class="o">.</span><span class="n">addDatabase</span><span class="p">(</span><span class="s1">'QMYSQL'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setHostName</span><span class="p">(</span><span class="s1">'localhost'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setDatabaseName</span><span class="p">(</span><span class="s1">'testbase'</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">setUserName</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="n">db</span><span class="o">.</span><span class="n">setPassword</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="n">ok</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">open</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ok</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_connection_status</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="s1">'Connection status: Ok'</span><span class="p">)</span>
<span class="n">QMessageBox</span><span class="o">.</span><span class="n">information</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'Information'</span><span class="p">,</span> <span class="s1">'Successful database connection'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_connection_status</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="s1">'Connection status: Failed'</span><span class="p">)</span>
<span class="n">QMessageBox</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'ERROR!'</span><span class="p">,</span> <span class="s1">'No database connection!'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">disconnect_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">setFocus</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">change_label_conn_status</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">label_connection_status</span><span class="o">.</span><span class="n">setText</span><span class="p">(</span><span class="s1">'Connection status: '</span> <span class="o">+</span> <span class="n">s</span><span class="p">)</span> <span class="c1">#текст не меняется</span>
<span class="k">def</span> <span class="nf">start_thread</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pushButton_connect</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">setEnabled</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mythread</span> <span class="o">=</span> <span class="n">MyThread</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_user</span><span class="o">.</span><span class="n">text</span><span class="p">(),</span> <span class="bp">self</span><span class="o">.</span><span class="n">lineEdit_passwd</span><span class="o">.</span><span class="n">text</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mythread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">QApplication</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span>
<span class="n">win</span> <span class="o">=</span> <span class="n">MainForm</span><span class="p">()</span>
<span class="n">win</span><span class="o">.</span><span class="n">show</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">exec_</span><span class="p">())</span>
</pre></div>Собственно проблемы:<br/>1. При дауне MySql, label_connection_status не изменяется на “failed”, хотя в консоль метод run() гадит print('Debug: Connection: Failed ' + db.lastError().text()), как и было задумано. Почему?<br/>2. Два потока (в конструкторе и в методе start_thread) - бред. Как избавиться от этого бреда? Как сделать правильно?<br/>3. Может быть можно как-то иначе реализовать проверку доступности MySql для соединения?<br/>Заранее благодарю.