Desktop Notifications in Python with Libnotify

Libnotify is part of the Gnome project and built on top of the Gnome library. Python has bindings to Gnome and we will take advantage of them to create desktop notifications. We can set the text, images, urgency, and create custom buttons in our notifications. Libnotify is a small and simple library and is a good place to start if you have never done any Gnome/Gtk programming. These examples will walk through all the options available.

Install Prerequisites

A base Debian install with Gnome install will not require any special packages to be installed. Here are some relevant packages though.

# This one is required, but should already be installed
sudo apt-get install python-gobject

# Installing this will install the
# notify-send program. Check that out
# for sending notifications in the shell
sudo apt-get install libnotify-bin

# The development headers if you
# want to do any development in C/C++
sudo apt-get install libnotify-dev

Hello World

Short enough you can type it right in to an interactive python interpreter.

from gi.repository import Notify
Notify.init("App Name")
Notify.Notification.new("Hi").show()

That is the shortest you can get a simple notify program. The notification object is created, and show() is immediately chained, but the object is never stored or used again. We can actually store the notification object that was created, and re-use later by calling show() again on the object. We will do that in the rest of the examples. We will also explore the options available.

Uninitializing

It is always good to clean up things when you are done. Libnotify provides an unitialize function that we should call whenever we are done using notifications.

Notify.uninit()

Hiding Notification

We can immediately close a notification by simply calling close().

# Close notification immediately
notification.close()

Hello Again

Check out another hello world notification program, but not as simplified as the first Python example. We import the gi.repository library. Gi stands for GObject Introspection, and is the layer between the Gnome libraries in C and bindings to other languages.

from gi.repository import Notify

# One time initialization of libnotify
Notify.init("My Program Name")

# Create the notification object
summary = "Wake up!"
body = "Meeting at 3PM!"
notification = Notify.Notification.new(
    summary,
    body, # Optional
)

# Actually show on screen
notification.show()

Once the object is created and stored in a variable, we can repeatedly call show() on the object to send the same notification.

Re-using Notification Object

Instead of creating new notification objects for every message, you can re-use the same object. You can just call show() again, but it would have the same message. You can change the properties before you show it again.

from gi.repository import Notify
Notify.init("My Program Name")

# Create the notification object and show once
notification = Notify.Notification.new("Hi")
notification.show()

# Let's throw in a sleep before we show again
import time
time.sleep(1)

# Change application name
notification.set_app_name("New App Name")

# Change summary and body
notification.update("Ding!", "Cupcakes are done.")

# Show again
notification.show()

Icons and Images

We can set the icon and image for the notification by creating a GdkPixbuf type image. We can easily load an image file using the new_from_file() function on the GdkPixbuf object. This will require importing GdkPixbuf module from the GObject Introspection repository (gi.repository).

# This time import the GdkPixbuf module
from gi.repository import Notify, GdkPixbuf

Notify.init("Test App")
notification = Notify.Notification.new("Alert!")

# Use GdkPixbuf to create the proper image type
image = GdkPixbuf.Pixbuf.new_from_file("/home/NanoDano/test.png")

# Use the GdkPixbuf image
notification.set_icon_from_pixbuf(image)
notification.set_image_from_pixbuf(image)

notification.show()

You can also specify an image file name to the new() function.

from gi.repository import Notify
Notify.init("Test App")

# A raw file name/path
Notify.Notification.new(
    "Ding!",
    "Time is up.",
    "/home/dtron/image.png"
).show()

# Or a icon name in the theme
Notify.Notification.new(
    "Ding!",
    "Time is up.",
    "dialog-information" # dialog-warn, dialog-error
).show()

When show() is called, there can be a delay if you use a large image file.

Adding Buttons/Actions to Notification

If you want the user to take some kind of action like "Reply" there is a way to add a button to the notification. Call add_action() like in the example below. Actions are a core part of Gnome programming. Actions are a topic of their own so I will only provide this snippet so that you know it is possible to use button clicks in the notification to trigger Gnome actions.

from gi.repository import Notify

Notify.init("Test App")

# Define a callback function
def my_callback_func():
    pass

notification = Notify.Notification.new("Hi!")
# The notification will have a button that says
# "Reply to Message". my_callback_func is something
# We will have to define
notification.add_action(
    "action_click",
    "Reply to Message",
    my_callback_func,
    None # Arguments
)

# Clear all actions with clear_actions()
#notification.clear_actions()

Different Urgency Levels

There are three urgency levels available: low, normal, and critical.

from gi.repository import Notify
Notify.init("Test App")

notification = Notify.Notification.new("Hi")

notification.set_urgency(0)
notification.set_urgency(1)
notification.set_urgency(2) # Highest priority

notification.show()

The notify-send Program

It is worth mentioning there is already a program available called notify-send. It is written in C, but the compiled program is part of the libnotify-bin package in Debian. It is good for scripting in bash shell. The entire notify-send program is one single file. To see how that is written in C, check out the notify-send.c source code. You can even find notify-send for Windows.

Install and use the notify-send program like this.

#!/bin/bash

# Install notify-send it if needed
sudo apt-get install libnotify-bin

# Basic usage. Script it.
notify-send "Hello"

# There are some options. check the man page.
man notify-send

You could even use a system call to just run the notify-send program. While that technically works, it is not the best way to do things if you want to control the objects in your code. We will move on to see how to do it all in Python.

#!/usr/bin/python
from subprocess import call
call(["notify-send", "Hello!", "Not the best way!"])

Other Languages

While my examples are aimed Debian distributions, I really like Arch Linux too. The Arch Linux wiki has a really great article on using libnotify. The dependencies they list may differ slightly just because the package name is different between Arch Linux and Debian, but it should be easy enough to find the same package for your distribution. The Arch Wiki page on desktop notifications covers a basic notification application in over a dozen languages. Libnotify is very simple so it is a good library to play with in unfamiliar languages.

References

The Libnotify documentation can be found on the Gnome Developer site.