问题
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)
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?
回答1:
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.
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.
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()
来源:https://stackoverflow.com/questions/32681532/python-program-with-notification-in-gnome-shell-doesnt-work