【问题标题】:Python post osx notificationPython 发布 osx 通知
【发布时间】:2013-07-15 09:35:16
【问题描述】:

我想使用 python 向 OSX 通知中心发布消息。 我需要使用什么库?我应该在objective-c中编写一个程序,然后从python调用该程序吗?


更新

如何访问 10.9 的通知中心功能,例如按钮和文本字段?

【问题讨论】:

  • 我回答了一个类似的问题here。代码使用pyobjc,但有一些问题

标签: python macos osx-mavericks


【解决方案1】:

这里的所有其他答案都需要第三方库;这个不需要任何东西。它只是使用苹果脚本来创建通知:

import os

def notify(title, text):
    os.system("""
              osascript -e 'display notification "{}" with title "{}"'
              """.format(text, title))

notify("Title", "Heres an alert")

请注意,此示例不会对引号、双引号或其他特殊字符进行转义,因此这些字符在通知的文本或标题中将无法正常工作。

更新:这应该适用于任何字符串,无需转义任何内容。它通过将原始字符串作为 args 传递给苹果脚本而不是尝试将它们嵌入到苹果脚本程序的文本中来工作。

import subprocess

CMD = '''
on run argv
  display notification (item 2 of argv) with title (item 1 of argv)
end run
'''

def notify(title, text):
  subprocess.call(['osascript', '-e', CMD, title, text])

# Example uses:
notify("Title", "Heres an alert")
notify(r'Weird\/|"!@#$%^&*()\ntitle', r'!@#$%^&*()"')

【讨论】:

  • 太棒了!您知道如何将通知保留更长时间,添加声音或图像吗?
  • @AndreaDiBiagio 确定!查看此处 (apple.co/2mXi1Sc ) 了解如何通过通知播放声音,查看此处 (apple.stackexchange.com/q/106904 ) 了解如何更改图标。添加声音很容易;添加图像更加困难......您可能必须动态创建applescript文件并捆绑并在那里设置图像。祝你好运!
  • 如何增加长住时间?
  • 您还可以显示永久通知by changing a setting,或通过将上述脚本中的notification 替换为alertdialog 来显示弹出警告。
  • 这是使用 Mac 中已经存在的应用程序的一种非常聪明的方法,为这个答案喝彩。
【解决方案2】:

你应该先用 Ruby 安装terminal-notifier,例如:

$ [sudo] gem install terminal-notifier

然后你就可以使用这个代码了:

import os

# The notifier function
def notify(title, subtitle, message):
    t = '-title {!r}'.format(title)
    s = '-subtitle {!r}'.format(subtitle)
    m = '-message {!r}'.format(message)
    os.system('terminal-notifier {}'.format(' '.join([m, t, s])))

# Calling the function
notify(title    = 'A Real Notification',
       subtitle = 'with python',
       message  = 'Hello, this is me, notifying you!')

你去吧:

【讨论】:

  • 终端通知程序安装在 /Library/Ruby 位置。用py2app打包python脚本时,生成的app没有终端通知器的功能,可能是py2app找不到终端通知器的位置。关于这个问题的任何建议
  • 有一个名为 pync 的 Python 项目,它封装了终端通知程序。也许您可以更新答案以提及它?
  • 对于无需安装额外依赖项的简单解决方案,您可以使用 AppleScript 发布通知。具体方法见my answer! (很抱歉在这里劫持了 cmets,只是想确保人们知道无需安装任何东西就可以实现 :))
  • 我们可以增加宽度或高度或这个弹出窗口吗?
【解决方案3】:

复制自:https://gist.github.com/baliw/4020619

以下对我有用。

import Foundation
import objc
import AppKit
import sys

NSUserNotification = objc.lookUpClass('NSUserNotification')
NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')

def notify(title, subtitle, info_text, delay=0, sound=False, userInfo={}):
    notification = NSUserNotification.alloc().init()
    notification.setTitle_(title)
    notification.setSubtitle_(subtitle)
    notification.setInformativeText_(info_text)
    notification.setUserInfo_(userInfo)
    if sound:
        notification.setSoundName_("NSUserNotificationDefaultSoundName")
    notification.setDeliveryDate_(Foundation.NSDate.dateWithTimeInterval_sinceDate_(delay, Foundation.NSDate.date()))
    NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)


notify("Test message", "Subtitle", "This message should appear instantly, with a sound", sound=True)
sys.stdout.write("Notification sent...\n")

【讨论】:

  • 有没有办法自定义通知中显示的图标?消息没有换行,有什么解决方法吗?
  • 是否可以设置回调,比如点击通知打开一个网址?
【解决方案4】:

对于仅 Python 的实现,我已经修改了某人作为另一个相关问题的一部分发布的代码,并且对我来说效果很好:

import mmap, os, re, sys
from PyObjCTools import AppHelper
import Foundation
import objc
import AppKit
import time
from threading import Timer

from datetime import datetime, date

# objc.setVerbose(1)

class MountainLionNotification(Foundation.NSObject):
    # Based on http://stackoverflow.com/questions/12202983/working-with-mountain-lions-notification-center-using-pyobjc

    def init(self):
        self = super(MountainLionNotification, self).init()
        if self is None: return None

        # Get objc references to the classes we need.
        self.NSUserNotification = objc.lookUpClass('NSUserNotification')
        self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')

        return self

    def clearNotifications(self):
        """Clear any displayed alerts we have posted. Requires Mavericks."""

        NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter')
        NSUserNotificationCenter.defaultUserNotificationCenter().removeAllDeliveredNotifications()

    def notify(self, title, subtitle, text, url):
        """Create a user notification and display it."""

        notification = self.NSUserNotification.alloc().init()
        notification.setTitle_(str(title))
        notification.setSubtitle_(str(subtitle))
        notification.setInformativeText_(str(text))
        notification.setSoundName_("NSUserNotificationDefaultSoundName")
        notification.setHasActionButton_(True)
        notification.setActionButtonTitle_("View")
        notification.setUserInfo_({"action":"open_url", "value":url})

        self.NSUserNotificationCenter.defaultUserNotificationCenter().setDelegate_(self)
        self.NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification)

        # Note that the notification center saves a *copy* of our object.
        return notification

    # We'll get this if the user clicked on the notification.
    def userNotificationCenter_didActivateNotification_(self, center, notification):
        """Handler a user clicking on one of our posted notifications."""

        userInfo = notification.userInfo()
        if userInfo["action"] == "open_url":
            import subprocess
            # Open the log file with TextEdit.
            subprocess.Popen(['open', "-e", userInfo["value"]])

您可能会清理导入语句以删除一些不需要的导入。

【讨论】:

  • 我知道这个答案很旧,但我在class MountainLionNotification(Foundation.NSObject)::objc.BadPrototypeError: Objective-C expects 1 arguments, Python argument has 5 arguments for <unbound selector notify of MountainLionNotification at 0x107990ce0> 收到错误。你知道如何解决它吗?
【解决方案5】:

另一个选择是一个名为 pyncpython 库,也许这是一个更好的选择。 pync 是围绕 terminal-notifier 命令行工具的简单 Python 包装器,可让您将用户通知发送到 Mac OS X 10.10 或更高版本的通知中心。

安装

pip 安装 pync

示例

from pync import Notifier

Notifier.notify('Hello World')
Notifier.notify('Hello World', title='Python')
Notifier.notify('Hello World', group=os.getpid())
Notifier.notify('Hello World', activate='com.apple.Safari')
Notifier.notify('Hello World', open='http://github.com/')
Notifier.notify('Hello World', execute='say "OMG"')

Notifier.remove(os.getpid())

Notifier.list(os.getpid())

【讨论】:

  • 像魅力一样工作!
【解决方案6】:

如果您还希望脚本能够通过其他设备与您通信,请尝试 ntfy

安装

[sudo] pip install ntfy 

其中pip指的是目标Python版本的Package Installer

对于 Python3 安装:

[sudo] pip3 install ntfy    

用法

我使用这个简单的函数来通知有关命令执行和下载完成:

def notification(title, message):
    """Notifies the logged in user about the download completion."""

    import os
    cmd = 'ntfy -t {0} send {1}'.format(title, message)
    os.system(cmd)

notification("Download Complete", "Mr.RobotS01E05.mkv saved at /path")

ntfy的优点

  1. 这个工具非常方便,因为它将所有通知直接记录到通知中心,而不是引用其他第三方应用程序。

  2. 多个后端支持:此工具可以通过 PushBullet、SimplePush、Slack、Telegram 等服务通过任何设备连接到您。查看支持的后端服务的完整列表here

    李>

【讨论】:

    【解决方案7】:

    这是一种方法(您需要 Foundation 模块):

    from Foundation import NSUserNotification
    from Foundation import NSUserNotificationCenter
    from Foundation import NSUserNotificationDefaultSoundName
    
    
    class Notification():
        def notify(self, _title, _message, _sound = False):
            self._title = _title
            self._message = _message
            self._sound = _sound
    
            self.notification = NSUserNotification.alloc().init()
            self.notification.setTitle_(self._title)
            self.notification.setInformativeText_(self._message)
            if self._sound == True:
                self.notification.setSoundName_(NSUserNotificationDefaultSoundName)
    
            center = NSUserNotificationCenter.defaultUserNotificationCenter()
            center.deliverNotification_(self.notification)
    
    N = Notification()
    N.notify(_title="SOME", _message="Something", _sound=True)
    

    这仅适用于 MAC。希望你喜欢!

    【讨论】:

    • 对于任何阅读本文的人,我基于这种方法制作了一个名为 simple-notifications 的 Python 库。希望它仍然相关。
    猜你喜欢
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多