2

Webページから情報を取得し、Gnome Shellの通知に表示するpythonプログラムを書いています。Arch を使っているので、起動時にこのプログラムを起動し、Web ページに変更があれば通知してくれるようにしたいです。これが私のコードです:

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)

問題は、通知の [続きを読む...] ボタンをクリックするとGLib.MainLoop().run()、create_notify 関数のコメントを外さない限り Firefox が開かず、プログラムがフリーズすることです。誰か助けてくれませんか?

4

1 に答える 1

6

GUI アプリケーションは通常、ウィジェット、イベント ループ、およびコールバックの 3 つの主要コンポーネントを使用します。そのアプリケーションを起動したら、ウィジェットを作成し、コールバックを登録して、イベント ループを開始します。イベント ループは、ウィジェットからのイベント (「クリックされたボタン」など) を探し、対応するコールバックを起動する無限ループです。

ここで、アプリケーションに別の無限ループがあるため、これら 2 つがうまくいきません。代わりに、 を使用してGLib.MainLoop().run()イベントを発生させる必要があります。GLib.timeout_add_seconds10 秒ごとなどの定期的なイベントを発生させるために使用できます。

2 番目の問題は、コールバックを呼び出すはずの通知への参照を保持する必要があることです。GLib.MainLoop().run()afterを追加したときに機能した理由は、へのnoti.show()参照がnotiまだ存在するためですが、以前に提案したように変更を加えると機能しません。アクティブな通知が常に 1 つだけであることが確実な場合は、最後の通知への参照を保持できます。そうしないと、リストが必要になり、定期的にパージするか、それに沿って何かを行う必要があります。

次の例は、正しい方向に設定する必要があります。

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()
于 2015-09-29T08:29:12.290 に答える