Отправление сообщения об ошибке в telegram [PyQt5]

Я пытаюсь интегрировать отправку сообщения об ошибках в telegram внутри PyQt5. Я ввёл комбинацию ctrl+x для создания ошибки. После этого должен создаваться файл с атрибутами win и отправиться вместе с текстом Traceback. Я пробовал:

import io
import sys
import asyncio
import traceback
import keyboard as k
from telegram import Bot
from qasync import QEventLoop
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox


TELEGRAM_TOKEN = 'TOKEN'
CHAT_ID = 'ID'

class Main_widget(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 1
        k.hook_key('ctrl', lambda e: self.switch(e))
        k.hook_key('x', lambda e: self.check(e))
        self.show()
    def switch(self, e):
        if 'down' in str(e):
            self.temp = True
        else:
            self.temp = False
    def check(self, e):
        if self.temp and 'down' in str(e):
            try:
                if e.name == 'x':
                    aa = 5 / 0
            except:
                ex_type, ex_val, ex_tb = sys.exc_info()
                excepthook(ex_type, ex_val, ex_tb)

async def send_report(tb, lines):
    bot = Bot(token=TELEGRAM_TOKEN)
    file_content = "\n".join(lines) or "Нет данных"
    file_stream = io.StringIO(file_content)
    file_stream.name = "attributes.txt"
    try:
        await bot.send_document(
            chat_id=CHAT_ID,
            document=file_stream,
            caption=f"Сообщение об ошибке:\n{tb}"
        )
    except Exception as e:
        print(f"Ошибка отправки в Telegram: {e}")
    finally:
        file_stream.close()


def excepthook(exc_type, exc_value, exc_tb):
    tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
    lines = []
    if win:
        for name, value in win.__dict__.items():
            if not callable(value) and not name.startswith("__"):
                lines.append(f"{name}: {value}")
    msg = QMessageBox()
    msg.setIcon(QMessageBox.Critical)
    msg.setWindowTitle("Ошибка")
    msg.setText("Во время работы программы возникла ошибка.")
    report = msg.addButton('Сообщить об ошибке и выйти', msg.ActionRole)
    report.clicked.connect(lambda: send_report(tb, lines))
    win.close()
    msg.show()

sys.excepthook = excepthook

if __name__ == "__main__":
    app = QApplication(sys.argv)
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)
    win = Main_widget()

    with loop:
        loop.run_forever()

Когда код должен показывать сообщение об ошибке, основное окно закрывается и больше ничего не происходит, хотя программа всё ещё работает. Пожалуйста, помогите разобраться


Ответы (1 шт):

Автор решения: Flevtek

Мой итоговый вариант:

import os
import sys
import requests
import traceback
import keyboard as k
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox


TOKEN = 'TOKEN'
CHAT_ID = 'ID'

class Main_widget(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 1
        k.hook_key('ctrl', lambda e: self.switch(e))
        k.hook_key('x', lambda e: self.check(e))
        self.show()
    def switch(self, e):
        if 'down' in str(e):
            self.temp = True
        else:
            self.temp = False
    def check(self, e):
        if self.temp and 'down' in str(e):
            try:
                if e.name == 'x':
                    aa = 5 / 0
            except:
                ex_type, ex_val, ex_tb = sys.exc_info()
                excepthook(ex_type, ex_val, ex_tb)

class Error(QObject):
    error = pyqtSignal(str, list, str)
    def __init__(self):
        super().__init__()
        self.error.connect(self.show_message)

    def show_message(self, tb, lines, ex_name):
        if 'win' not in globals():
            url = f"https://api.telegram.org/bot{TOKEN}/sendMessage"
            requests.post(url, data={"chat_id": CHAT_ID, 'text': tb})
            msg = QMessageBox()
            msg.setWindowTitle("Ошибка")
            msg.setText("При запуске программы возникла ошибка.")
            msg.setIcon(QMessageBox.Critical)
            msg.setInformativeText("Мы уже сообщили об этом разработчику.")
            msg.setDetailedText(ex_name)
            msg.addButton('Закрыть', msg.YesRole)
            msg.exec_()
            return
        win.close()
        msg = QMessageBox()
        msg.setWindowTitle("Ошибка")
        msg.setText("Во время работы программы произошла ошибка.")
        msg.setIcon(QMessageBox.Critical)
        msg.setInformativeText("Мы уже сообщили об этом разработчику.")
        msg.setDetailedText(ex_name)
        msg.addButton('Закрыть', msg.YesRole)
        msg.exec_()
        filename = 'report.txt'
        with open(filename, 'w') as file:
            file.writelines(lines)
        url_file = f"https://api.telegram.org/bot{TOKEN}/sendDocument"
        with open(filename, "rb") as file:
            requests.post(url_file, data={"chat_id": CHAT_ID, 'caption': tb}, files={"document": file})
        os.remove(filename)


def excepthook(exc_type, exc_value, exc_tb):
    tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
    lines = []
    if 'win' in globals():
        for name, value in win.__dict__.items():
            if not callable(value) and not name.startswith("__"):
                lines.append(f"{name}: {value}")
    error.error.emit(tb, lines, exc_type.__name__)


if __name__ == "__main__":
    sys.excepthook = excepthook
    app = QApplication(sys.argv)
    error = Error()
    win = Main_widget()
    sys.exit(app.exec_())
→ Ссылка