N
N
Nur Kasimov2016-08-08 12:15:38
Python
Nur Kasimov, 2016-08-08 12:15:38

Why does the program crash when calling setHtml?

The program downloads an html page from the web and displays it in a QTextBrowser with the setHtml function, and then 4 more pictures and displays them in a QLabel.
Because loading the page and pictures takes time, and for this time the program stopped responding (hangs), fixed it - moved it into a separate class inherited from QThread (into a separate thread), and in the main class only called it at a certain moment. And if there were no problems with the pictures, then there were some problems with QTextBrowser - in the line myapp.textBrowser.setHtml(res.text) the program crashes without explanation and without having time to display the pictures and the page itself, catching the error does not help.
If you comment out the line, then the program continues to work properly, loading pictures and displaying them.
Is this a bug of QTextBrowser itself? Am I missing something (I'm new)? Is there a way to fix it or will I have to use other forms?
Problematic piece of code:

# python3
if os.path.exists("temp/"+trek+".html"):  # Если страница уже была ранее загружена
    with open("temp/"+trek+".html") as w:
        myapp.textBrowser.setHtml(w.read())  # Вылетает здесь
else:
    res = requests.get('http://URL/'+trek+".html") 
    res.encoding = 'utf-8'
    with open("temp/"+trek+".html", "w") as ri:
        ri.write(res.text)
    myapp.textBrowser.setHtml(res.text)  # И здесь

PS If the program does not find the page in the temporary folder, loads it on a new one and crashes, then this page remains in this folder. the program ended incorrectly and when restarted it no longer downloads, but still crashes.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey6661313, 2016-08-14
@luchs

res = requests.get('http:// URL /'+trek+".html")
orly?
Well, by God, they wrote at least "yandex.ru/index.html" for an example.
Without explaning the reason
Well, please use pycharm - there is a free edition. It honestly opens a console for every program that is running. In which the reason is honestly written. And which, most importantly, does not close after an error.
pieces of code should be made minimal, BUT runnable. for example like this:
import sys
import requests
import os
from PyQt5.QtWidgets import QTextBrowser
from PyQt5.Qt import QApplication
from PyQt5.Qt import QThread

trek = "index"
myapp = QApplication(sys.argv)
myapp.textBrowser = QTextBrowser()

class ExperementalThread(QThread):
    def run(self):
        if os.path.exists("temp/"+trek+".html"):  # Если страница уже была ранее загружена
            with open("temp/"+trek+".html") as w:
                myapp.textBrowser.setHtml(w.read())  # ни разу не вылетело
        else:
            res = requests.get('http://yandex.ru/'+trek+".html")
            res.encoding = 'utf-8'
            with open("temp/"+trek+".html", "w") as ri:
                ri.write(res.text)
            myapp.textBrowser.setHtml(res.text)  # И здесь

thread = ExperementalThread()
myapp.textBrowser.show()
thread.start()
myapp.exec()

and error resp. would be QObject: Cannot create children for a parent that is in a different thread.
which means that the setHtml method is trying to create a separate thread for itself. And father Lenin himself forbade creating flows from flows (quote from ██.██/19██).
So you have to use signals and slots.
i created my class MyQTextBrowser with QTextBrowser inheritance and signal_load_html signal. Which in turn is linked to setHTML.
# coding=utf-8

import sys, requests, os                            # импортировали,
from PyQt5.Qt        import QApplication, QThread   # импортировали,
from PyQt5.QtCore    import pyqtSignal              # да не
from PyQt5.QtWidgets import QTextBrowser            # выпереимпортировали.

trek = "index"                                      # ну в самом деле надо же указать чему равна ваша переменная.
myapp = QApplication(sys.argv)                      # я угадал?
                                                    # обязательно делаем отступы перед каждым классом
class MyQTextBrowser(QTextBrowser):                 # создаём класс и наследуем QTextBrowser
    signal_load_html = pyqtSignal(str)              # назначаем сигнал (сигнал принимает значение str (строки) )
                                                    # тут тоже отступ
    def __init__(self):                             # переназначаем метод создания объектов
        super().__init__()                          # наследуем/выполняем QTextBrowser.__init__(self)
        self.signal_load_html.connect(self.setHtml) # тут связываем наш сигнал с setHtml
myapp.textBrowser = MyQTextBrowser()                # ну и создаём вообщемто обьект нашего класса MyQTextBrowser
                                                    # обязательно делаем отступы после каджого класса.
                                                    # обязательно делаем отступы перед каждым классом
class ExperementalThread(QThread):                  # названия придумываем на ходу
    def run(self):                                  # init не нужен сразу run
        if os.path.exists("temp/"+trek+".html"):    # Если страница уже была ранее загружена
            with open("temp/"+trek+".html") as w:   # открываем наш фаил в папке temp
                # myapp.textBrowser.setHtml(w.read())  # вылетает? у меня кстати нет, но я читер :)
                myapp.textBrowser.signal_load_html.emit(w.read())  # ни разу не вылетело.
        else:                                       # люблю когда много коментариев в коде
            res = requests.get('http://yandex.ru/'+trek+".html") # "Люблю говорить - это помогает думать."
            res.encoding = 'utf-8'                  # -- Томас Стернз Элиот
            with open("temp/"+trek+".html", "w") as ri: # когда этот код уже кончится?
                ri.write(res.text)                  # тут пусто потому что в оригинале у вас был "URL" а не yandex
            # myapp.textBrowser.setHtml(res.text)   # И здесь
            myapp.textBrowser.signal_load_html.emit(res.text)  # ни разу не вылетело
                                                    # обязательно делаем отступы после каждого класса.
thread = ExperementalThread()                       # создаём наш поток
myapp.textBrowser.show()                            # ах да - самое главное показать окно. Иначе ничего не произойдёт
thread.start()                                      # запускаем поток
myapp.exec()                                        # Ой, всё!()

ps
Generally setHtml is not a QTextBrowser method. This is a method from QTextEdit (which QTextBrowser inherits. ) QTextBrowser itself is designed to load and display web pages on its own. (by url.)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question