import pynotify
import gobject
def on_clicked(notification, signal_text):
print "1: " + str(notification)
print "2: " + str(signal_text)
notification.close()
def on_closed(notification):
print "on_closed"
notification.close()
def show_notification(title, body):
n = pynotify.Notification(title, body)
n.add_action("button", "Test button", on_clicked)
n.connect("closed", on_closed)
n.show()
if __name__ == '__main__':
pynotify.init('TestApp')
global loop
loop = gobject.MainLoop()
# first case
notify = pynotify.Notification("1_notify", "test")
notify.add_action("button", "Test button", on_clicked)
notify.connect("closed", on_closed)
notify.show()
# second case
show_notification("2_notify", "test")
loop.run()
Sorry for my bad English. I want to handle closing xfce4-notifyd notification. In the first case, the function "on_closed()" works. Why in the second case it does not work?
This only works well in one namespace?
It does not work because the Notification object goes out of scope when show_notification() returns and is freed. You can make it work by e.g. returning the Notification object from the function and storing it in a variable in main body.
Related
New to click here so I'm still learning. How do I store the click arguments/options in an object for later reference within my application? I thought of just creating an object and returning it from the setup function, but it doesn't seem to work. Here is what I did:
import click
import sys
class Cfg(object):
component = ""
command = ""
obj = ""
my_cfg = Cfg()
#click.command()
#click.argument('component')
#click.argument("command")
#click.argument("obj")
def set_args(component, command, obj):
cfg = Cfg()
if component != "optdata":
sys.stderr.write("Invalid option")
sys.exit(1)
else:
cfg.component = component
cfg.command = command
cfg.obj = obj
return cfg
if __name__ == "__main__":
app_cfg = Cfg()
app_cfg = set_args() # Never actually completes here.
print("Component = ", app_cfg.component, "Command = ", app_cfg.command, "Obj = ", app_cfg.obj)
There is some sort of exception raised in core.py which just does a sys.exit and doesn't raise any sort of actual error.
Your design goes against the idea of Click: You're not supposed to treat "parsing the options" and "doing the work" as two separate steps:
import click
#click.command()
#click.argument("component", type=click.Choice(["optdata"]))
#click.argument("command")
#click.argument("obj")
def cli(component, command, obj):
print("Component = ", component, "Command = ", command, "Obj = ", obj)
# put your business logic here
if __name__ == "__main__":
cli()
The pattern is to call the function that processes the command line options and then have that function call any other functionality.
I recognize this may be a very 101 type question, but I'm still having trouble understanding functional programming in general, and have a particular code snippet that I can't make sense of:
Full code, but leaving out most of the function definitions:
import blpapi
import sys
SESSION_STARTED = blpapi.Name("SessionStarted")
SESSION_STARTUP_FAILURE = blpapi.Name("SessionStartupFailure")
SERVICE_OPENED = blpapi.Name("ServiceOpened")
SERVICE_OPEN_FAILURE = blpapi.Name("ServiceOpenFailure")
ERROR_INFO = blpapi.Name("ErrorInfo")
GET_FILLS_RESPONSE = blpapi.Name("GetFillsResponse")
d_service="//blp/emsx.history"
d_host="localhost"
d_port=8194
bEnd=False
class SessionEventHandler():
def processEvent(self, event, session):
try:
if event.eventType() == blpapi.Event.SESSION_STATUS:
self.processSessionStatusEvent(event,session)
elif event.eventType() == blpapi.Event.SERVICE_STATUS:
self.processServiceStatusEvent(event,session)
elif event.eventType() == blpapi.Event.RESPONSE:
self.processResponseEvent(event)
else:
self.processMiscEvents(event)
except:
print ("Exception: %s" % sys.exc_info()[0])
return False
def processSessionStatusEvent(self,event,session):
print ("Processing SESSION_STATUS event")
for msg in event:
pass
def processServiceStatusEvent(self,event,session):
print ("Processing SERVICE_STATUS event")
for msg in event:
pass
def processResponseEvent(self, event):
print ("Processing RESPONSE event")
for msg in event:
global bEnd
bEnd = True
def processMiscEvents(self, event):
print ("Processing " + event.eventType() + " event")
for msg in event:
print ("MESSAGE: %s" % (msg.tostring()))
def main():
sessionOptions = blpapi.SessionOptions()
sessionOptions.setServerHost(d_host)
sessionOptions.setServerPort(d_port)
print ("Connecting to %s:%d" % (d_host,d_port))
eventHandler = SessionEventHandler()
session = blpapi.Session(sessionOptions, eventHandler.processEvent)
if not session.startAsync():
print ("Failed to start session.")
return
global bEnd
while bEnd==False:
pass
session.stop()
I can follow the code up to here:
session = blpapi.Session(sessionOptions, eventHandler.processEvent)
Here, I see I'm calling "Session" from the blpapi library, and passing it some options as well as my eventHandler.processEvent. Here is where I get lost. I look at that particular function, and see:
def processEvent(self, event, session):
try:
if event.eventType() == blpapi.Event.SESSION_STATUS:
self.processSessionStatusEvent(event,session)
elif event.eventType() == blpapi.Event.SERVICE_STATUS:
self.processServiceStatusEvent(event,session)
elif event.eventType() == blpapi.Event.RESPONSE:
self.processResponseEvent(event)
else:
self.processMiscEvents(event)
except:
print ("Exception: %s" % sys.exc_info()[0])
return False
I see that the function is attempting to discern what type of event has been passed in, and will execute a different function within the class depending on that event type. The trouble is, I can't figure out where the event is ever specified! Where does "event" come from? I see it as an argument in that particular function, but no event argument was passed to:
session = blpapi.Session(sessionOptions, eventHandler.processEvent)
So how does it know what to do at this point? How did this "event" object magically appear?
Thanks for entertaining my dumb questions
session = blpapi.Session(sessionOptions, eventHandler.processEvent)
Note that processEvent here lacks parentheses () after it. This means you are passing the function itself as a parameter to the Session class. This class will later call processEvent with appropriate parameters.
Side Note:
I'm still having trouble understanding functional programming
"Functional programming" has a very specific definition and this example isn't it. If you are interested, you can google "functional programming" or read the Wikipedia article to find out more. However, this isn't really important at this stage in your learning process.
I would like to write cmd-line application with Python, which in the upper part of the terminal shows the status of something, I'd like to monitor, while in the lower part I (and my colleages) have the normal ipython interpreter, which allows us to manipulate the behaviour of the application.
In order to show the status display, I was thinking of using blessings. At first I thought about using cmd or cmd2 in order to allow run-time manipulation of the status display, but then I though, why should one implement a lot of do_something methods, when one can have the same functionality (including tab-completion and online help) for free, using the ipython interpreter.
Here is my first approach
## -- first_try.py
import time
import random
from threading import Thread
from blessings import Terminal
term = Terminal()
def display_func1():
print time.asctime()
print "Some int: ", random.randint(0, 10)
print "Some float: ", random.random()*10
def display_func2():
print time.asctime()
print "Some int: ", random.randint(0, 10)
print " details:", [random.randint(0, 10) for i in range(7)]
print "Some float: ", random.random()*10
print " details:", [random.random()*10 for i in range(5)]
class StatusDisplay(Thread):
def __init__(self, display_func):
self._text = ""
self._stop = False
self.display = display_func
Thread.__init__(self)
def run(self):
while not self._stop:
with term.location():
self.clear_top_lines()
print term.move(0, 0)
print 70*'-'
self.display()
print 70*'-'
self.print_help()
time.sleep(0.1)
def stop(self):
self._stop = True
def print_help(self):
print
print "In order to manipulate the status display"
print "type: "
print " sd.display = display_func2 and if you want to go back."
print " sd.display = display_func1"
print " Or implement your own display function and hook it into the display"
def clear_top_lines(self, n=10):
with term.location():
for i in range(n):
print term.move(0, i) + term.clear_eol()
time.sleep(2)
sd = StatusDisplay(display_func1)
sd.daemon = True
sd.start()
When I invoke this script, e.g. like this:
ipython -i --no-banner first_try.py
And hit a couple of times enter, then I have in the top of the page, something that looks like the status display, I'd like to have, and in the lower part, I can still work with the ipython interpreter, due to the -i parameter.
I think I am working here in the wrong direction, but I really would like to have this kind of feature in my application. Can somebody give me a push into the right direction?
I am trying to create a object from a array when a new port is opened en delete it when it is closet.
#!/usr/bin/python
import thread
import psutil
import time
thelist = []
class connection:
def __init__(self, name):
self.name = name
print "open van stream" + str(self.name)
def __del__(self):
print "close van stream "
def contains(list, filter):
for x in list:
if filter(x):
return True
return False
if __name__ == '__main__':
try:
PROCNAME = "tvheadend"
for proc in psutil.process_iter():
if proc.name == PROCNAME:
process = proc
if not process:
print "not found tvheadend"
exit()
print "Found " + str(process)
while(1):
for list in process.get_connections(kind='udp'):
if not contains(thelist, lambda x: x.name == list.local_address[0]):
thelist.append(connection(list.local_address[0]))
for list in thelist:
print thelist
if not contains(process.get_connections(kind='udp'), lambda x: x.local_address[0] == list.name):
thelist.remove(list)
print "removed"
time.sleep(0.5)
except SystemExit, KeyboardInterrupt:
exit()
but it only prints "close van stream" when i open a new one. not when i close one. With the "print thelist" function i can see that the object is removed from the array but it does not print "close van stream"
As long as you still reference it from list, it is not gone.
It is only gone as soon as you re-assign list.
Only then will the reference counter of this object drop to 0 and __del__ will be called.
BTW, it is a bad idea to call a variable list, because this shadows the built-in type list.
And, BTW, __del__ should not be relied on. Instead, you should consider to define and use a context manager.
EDIT: The context manager thing is obviously not possible here, but you should .close() it explicitly instead of relying on __del__() being called.
I'm having a problem stopping the 'feed'; the cancel argument doesn't seem to have any impact on the after method. Although "feed stopped" is printed to the console.
I'm attempting to have one button that will start the feed and another that will stop the feed.
from Tkinter import Tk, Button
import random
def goodbye_world():
print "Stopping Feed"
button.configure(text = "Start Feed", command=hello_world)
print_sleep(True)
def hello_world():
print "Starting Feed"
button.configure(text = "Stop Feed", command=goodbye_world)
print_sleep()
def print_sleep(cancel=False):
if cancel==False:
foo = random.randint(4000,7500)
print "Sleeping", foo
root.after(foo,print_sleep)
else:
print "Feed Stopped"
root = Tk()
button = Button(root, text="Start Feed", command=hello_world)
button.pack()
root.mainloop()
With the output:
Starting Feed
Sleeping 4195
Sleeping 4634
Sleeping 6591
Sleeping 7074
Stopping Feed
Sleeping 4908
Feed Stopped
Sleeping 6892
Sleeping 5605
The problem is that, even though you're calling print_sleep with True to stop the cycle, there's already a pending job waiting to fire. Pressing the stop button won't cause a new job to fire but the old job is still there, and when it calls itself, it passes in False which causes the loop to continue.
You need to cancel the pending job so that it doesn't run. For example:
def cancel():
if self._job is not None:
root.after_cancel(self._job)
self._job = None
def goodbye_world():
print "Stopping Feed"
cancel()
button.configure(text = "Start Feed", command=hello_world)
def hello_world():
print "Starting Feed"
button.configure(text = "Stop Feed", command=goodbye_world)
print_sleep()
def print_sleep():
foo = random.randint(4000,7500)
print "Sleeping", foo
self._job = root.after(foo,print_sleep)
Note: make sure you initialize self._job somewhere, such as in the constructor of your application object.
When you call root.after(...), it will return an identifier. You should keep track of that identifier (e.g., store it in an instance variable), and then you can later call root.after_cancel(after_id) to cancel it.
Here is my answer with only 3 lines of code added. The answer lies in using .after_cancel(x) which in simple words, mean that "stop doing 'x' job". I believe in readability of code so I made only minimal changes to your code which did the job. Please have a look. Thanks.
from tkinter import Tk, Button
import random
keep_feeding = None
def goodbye_world():
print("Stopping Feed")
button.configure(text="Start Feed", command=hello_world)
print_sleep(True)
def hello_world():
print("Starting Feed")
button.configure(text="Stop Feed", command=goodbye_world)
print_sleep()
def print_sleep(cancel=False):
global keep_feeding
if not cancel:
foo = random.randint(1000, 2500)
print(f"Sleeping {foo}")
keep_feeding = root.after(foo, print_sleep)
else:
root.after_cancel(keep_feeding)
print("Feed Stopped")
root = Tk()
button = Button(root, text="Start Feed", command=hello_world)
button.pack()
root.mainloop()