Программа Python с уведомлением в Gnome Shell не работает

Я пишу программу на Python, которая берет информацию с веб-страницы и показывает ее в уведомлении в Gnome Shell. Я использую Arch, поэтому я хочу запускать эту программу при запуске, и если на веб-странице будут какие-либо изменения, она уведомит меня. Вот мой код:

import time
import webbrowser
import requests
from bs4 import BeautifulSoup
from gi.repository import Notify, GLib


IPS = {'Mobifone': True, 'Viettel': False, 'Vinaphone': False}
LINK = "https://id.vtc.vn/tin-tuc/chuyen-muc-49/tin-khuyen-mai.html"


def set_ips_state(ips_name, state):
    global IPS
    for key in IPS.iterkeys():
        if key == ips_name:
            IPS[key] = state


def call_webbrowser(notification, action_name, link):
    webbrowser.get('firefox').open_new_tab(link)


def create_notify(summary, body, link):
    Notify.init("Offer")
    noti = Notify.Notification.new(summary, body, 'dialog-information')
    noti.add_action('action_click', 'Read more...', call_webbrowser, link)
    noti.show()
    # GLib.MainLoop().run()


def save_to_file(path_to_file, string):
    file = open(path_to_file, 'w')
    file.write(string)
    file.close()


def main():
    global IPS
    global LINK

    result = []

    offer_news = open('offer_news.txt')
    tag_in_file = BeautifulSoup(offer_news.readline(), 'html.parser')
    tag = tag_in_file.a
    offer_news.close()

    page = requests.get(LINK)
    soup = BeautifulSoup(page.text, 'html.parser')
    for div in soup.find_all('div', 'tt_dong1'):
        # first_a = div.a
        # main_content = first_a.find_next_subling('a')
        main_content = div.find_all('a')[1]
        for k, v in IPS.iteritems():
            if v:
                if main_content.text.find(k) != -1:
                    result.append(main_content)
    print result[1].encode('utf-8')
    if tag_in_file == '':
        pass
    else:
        try:
            old_news_index = result.index(tag)
            print old_news_index
            for idx in range(old_news_index):
                create_notify('Offer News', result[idx].text.encode('utf-8'), result[idx].get('href'))
            print "I'm here"
        except ValueError:
            pass
    offer_news = open('offer_news.txt', 'w')
    offer_news.write(result[0].__str__())
    offer_news.close()


if __name__ == '__main__':
    while 1:
        main()
        time.sleep(10)

Проблема в том, что когда я нажимаю кнопку "Подробнее..." в уведомлении, он не открывает Firefox, пока я не раскомментирую GLib.MainLoop().run() в функции create_notify, но это приводит к зависанию программы. Кто-нибудь может помочь?


person mozart    schedule 20.09.2015    source источник


Ответы (1)


Приложения с графическим интерфейсом обычно используют три основных компонента: виджеты, цикл событий и обратные вызовы. Когда вы запускаете это приложение, вы создаете виджеты, регистрируете обратные вызовы и запускаете цикл обработки событий. Цикл событий — это бесконечный цикл, который ищет события от виджетов (например, «нажатие кнопки») и запускает соответствующие обратные вызовы.

Теперь в вашем приложении есть еще один бесконечный цикл, так что эти два не будут подыгрывать. Вместо этого вы должны использовать GLib.MainLoop().run() для запуска событий. Вы можете использовать GLib.timeout_add_seconds для запуска периодических событий, таких как каждые 10 секунд.

Вторая проблема заключается в том, что вам нужно хранить ссылку на уведомление, которое должно вызывать обратные вызовы. Причина, по которой это сработало, когда вы добавили GLib.MainLoop().run() после noti.show(), заключается в том, что ссылка на noti все еще существует, но это не сработает, если вы внесете изменения, как я предлагал ранее. Если вы уверены, что всегда будет активным только одно уведомление, вы можете сохранить ссылку на последнее уведомление. В противном случае вам понадобится список и периодическая его очистка или что-то в этом роде.

Следующий пример должен направить вас в правильном направлении:

from gi.repository import GLib, Notify


class App():
    def __init__(self):
        self.last_notification = None
        Notify.init('Test')
        self.check()

    def check(self):
        self.last_notification = Notify.Notification.new('Test')
        self.last_notification.add_action('clicked', 'Action', 
                                          self.notification_callback, None)
        self.last_notification.show()
        GLib.timeout_add_seconds(10, self.check)

    def notification_callback(self, notification, action_name, data):
        print(action_name)


app = App()
GLib.MainLoop().run()
person Fenikso    schedule 29.09.2015