Gnome Shell中带有Notification的Python程序不起作用 [英] Python program with Notification in Gnome Shell doesn't work

查看:172
本文介绍了Gnome Shell中带有Notification的Python程序不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个python程序,该程序从网页获取信息并在Gnome Shell中的Notification上显示.我正在使用Arch,因此我想在启动时启动该程序,如果网页上有任何更改,它将通知我.这是我的代码:

I'm writing a python program that takes info from a webpage and show it on Notification in Gnome Shell. I'm using Arch, so I want to start this program at startup and if there is any change on the webpage, it will notify me. Here is my code:

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)

问题是,当我单击通知中的阅读更多..."按钮时,除非我在create_notify函数中取消对GLib.MainLoop().run()的注释,否则它不会打开Firefox,但这会使程序冻结.有人可以帮忙吗?

The problem is when I click on "Read more..." button in the Notification, it does not open Firefox unless I uncomment GLib.MainLoop().run() in create_notify function, but that makes the program freeze. Could anybody help?

推荐答案

GUI应用程序通常使用三个主要组件:小部件,事件循环和回调.启动该应用程序时,您将创建小部件,注册回调并启动事件循环.事件循环是无限循环,它从小部件(例如单击的按钮")中查找事件并触发相应的回调.

The GUI applications usually use three main components: widgets, event loop and callbacks. When you start that application, you create widgets, register callbacks and start event loop. Event loop is infinite loop which looks for events from widgets (such as 'clicked button') and fires corresponding callbacks.

现在,在您的应用程序中,您还有另一个无限循环,因此这两个循环将不起作用.相反,您应该使用GLib.MainLoop().run()触发事件.您可以使用GLib.timeout_add_seconds触发定期事件,例如每10秒触发一次.

Now, in your application you have another infinite loop, so these two will not play along. Instead, you should make use of the GLib.MainLoop().run() to fire events. You can use GLib.timeout_add_seconds to fire periodic events such as your every 10 seconds.

第二个问题是,您需要保留对应该调用回调的通知的引用.在noti.show()之后添加GLib.MainLoop().run()时,它起作用的原因是对noti的引用仍然存在,但是如果您按照我之前的建议进行更改,则它不起作用.如果您确定总是只有一个通知处于活动状态,则可以保留对最后一个通知的引用.否则,您将需要一个列表并定期清除它或其他内容.

Second problem is that you need to hold reference to a notification which is supposed to call callbacks. The reason why it worked when you added GLib.MainLoop().run() after noti.show() is that reference to noti still exists, but it would not work if you would do changes as I have suggested earlier. If you are sure there is always going to be just one notification active, you can hold the reference to the last notification. Otherwise you would need a list and periodically purge it or something along the lines.

以下示例将为您设定正确的方向:

The following example should set you in the right direction:

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()

这篇关于Gnome Shell中带有Notification的Python程序不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆