Package: desktop-notifier
Desktop Notifierdesktop-notifieris a Python library for cross-platform desktop notifications.
Currently supported platforms are:Linux via the dbus service org.freedesktop.NotificationsmacOS and iOS via the Notification Center framework[exprimental] Windows via the WinRT / Python bridge.Featuresdesktop-notifieraims to be a good citizen of the platforms which it supports. It
therefore stays within the limits of the native platform APIs and does not try to work
around limitations which are often deliberate UI choices. For example, on macOS  and
iOS, it is not possible to change the app icon which is shown on notifications. There
are possible workarounds - that would likely be rejected by an App Store review - and
desktop-notifier deliberately stays away from those.Where supported by the native platform APIs,desktop-notifierallows for:Clickable notifications with callbacks on user interactionMultiple action buttonsA single reply field (e.g., for chat notifications)Notification soundsNotification threads (grouping notifications by topic)Limiting the maximum number of notifications shown in the notification centerAn exhaustive list of features and their platform support is provided in thedocumentation.Design choices bydesktop-notifier:Async API: The main API consists of async methods and a running event loop
is required to respond to user interactions with a notification.Prefer pure Python dependencies over extension modules. We make an exception for
Windows because interoperability with the Windows Runtime is difficult to achieve
otherwise.InstallationFrom PyPI:pip3 install -U desktop-notifierUsageThe main API consists of asynchronous methods which need to be awaited. Basic usage only
requires the user to specify a notification title and message. For example:importasynciofromdesktop_notifierimportDesktopNotifiernotifier=DesktopNotifier()asyncdefmain():n=awaitnotifier.send(title="Hello world!",message="Sent from Python")awaitasyncio.sleep(5)# wait a bit before clearing notificationawaitnotifier.clear(n)# removes the notificationawaitnotifier.clear_all()# removes all notifications for this appasyncio.run(main())For convenience, there is also a synchronous methodsend_sync()to send
notifications without manually starting an asyncio event loop:notifier.send_sync(title="Hello world!",message="Sent from Python")By default, "Python" will be used as the app name for all notifications, but you can
manually specify an app name and icon in theDesktopNotifierconstructor. Advanced
usage also allows setting different notification options such as urgency, buttons,
callbacks, etc. The following code will generate the notification shown in the gif at
the top of the page:importasynciofromdesktop_notifierimportDesktopNotifier,Urgency,Button,ReplyFieldnotifier=DesktopNotifier()asyncdefmain():awaitnotifier.send(title="Julius Caesar",message="Et tu, Brute?",urgency=Urgency.Critical,buttons=[Button(title="Mark as read",on_pressed=lambda:print("Marked as read")),],reply_field=ReplyField(title="Reply",button_title="Send",on_replied=lambdatext:print("Brutus replied:",text),),on_clicked=lambda:print("Notification clicked"),on_dismissed=lambda:print("Notification dismissed"),sound=True,)loop=asyncio.get_event_loop()loop.create_task(main())loop.run_forever()Note that some platforms may not support all options. For instance, some Linux desktop
environments may not support notifications with buttons. macOS does not support manually
setting the app icon or name. Instead, both are always determined by the application
which uses the Library. This can be Python itself, or a frozen app bundle when packaged
with PyInstaller or similar solutions. Please refer to thePlatform Supportchapter of the documentation for more information on limitations for certain platforms.Any options or configurations which are not supported by the platform will be silently
ignored.Event loop integrationUsing the asynchronous API is highly recommended to prevent multiple milliseconds of
blocking IO from DBus or Cocoa APIs. In addition, execution of callbacks requires a
running event loop. On Linux, an asyncio event loop will be sufficient but macOS
requires a runningCFRunLoop.You can userubicon-objcto integrate a Core
Foundation CFRunLoop with asyncio:importasynciofromrubicon.objc.eventloopimportEventLoopPolicy# Install the event loop policyasyncio.set_event_loop_policy(EventLoopPolicy())# Get an event loop, and run it!loop=asyncio.get_event_loop()loop.run_forever()Desktop-notifier itself uses Rubicon Objective-C to interface with Cocoa APIs. A full
example integrating with the CFRunLoop is given inexamples/eventloop.py. Please refer to theRubicon Objective-C docsfor more information.Likewise, you can integrate the asyncio event loop with a Gtk main loop on Gnome usinggbulb. This is not required for full functionality
but may be convenient when developing a Gtk app.Notes on macOSOn macOS 10.14 and higher, the implementation uses theUNUserNotificationCenterinstead of the deprecatedNSUserNotificationCenter.UNUserNotificationCenteronly allows signed executables to send desktop notifications. This means that
notifications will only work if the Python executable or bundled app has been signed.
Note that the installer frompython.orgprovides a properly signed
Python framework buthomebrew does not(manually signing the executable installed
by homebrewshouldwork as well).If you freeze your code with PyInstaller or a similar packaging solution, you must sign
the resulting app bundle for notifications to work. An ad-hoc signature will be
sufficient but signing with an Apple developer certificate is recommended for
distribution and may be required on future releases of macOS.RequirementsmacOS 10.13 or higherLinux desktop environment providing a dbus desktop notifications serviceDependenciesdbus-nexton Linuxrubicon-objcon macOSwinsdkon Windows