Python发布osx通知

时间:2013-07-15 09:35:16

标签: python macos osx-mavericks

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


更新

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

7 个答案:

答案 0 :(得分:67)

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

import os

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

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

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

答案 1 :(得分:50)

您应首先使用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!')

然后你去了:

enter image description here

答案 2 :(得分:15)

复制自: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")

答案 3 :(得分:9)

对于仅限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"]])

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

答案 4 :(得分:3)

另一个选择是名为{strong> pyncconst express = require('express'); const router = express.Router(); const fs = require('fs'); const readline = require('readline'); const {google} = require('googleapis'); const admin = require('firebase-admin'); var serviceAccount = require("../../serviceAccountKey.json"); // make environment variable admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "database" // actual url to the database in my code }); let db = admin.firestore(); // If modifying these scopes, delete token.json. const SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']; // The file token.json stores the user's access and refresh tokens, and is // created automatically when the authorization flow completes for the first // time. const TOKEN_PATH = 'token.json'; /** * Create an OAuth2 client with the given credentials, and then execute the * given callback function. * @param {Object} credentials The authorization client credentials. * @param {function} callback The callback to call with the authorized client. */ function authorize(credentials, callback) { const {client_secret, client_id, redirect_uris} = credentials.installed; const oAuth2Client = new google.auth.OAuth2( client_id, client_secret, redirect_uris[0]); // Check if we have previously stored a token. fs.readFile(TOKEN_PATH, (err, token) => { if (err) return getNewToken(oAuth2Client, callback); oAuth2Client.setCredentials(JSON.parse(token)); callback(oAuth2Client); }); } /** * Get and store new token after prompting for user authorization, and then * execute the given callback with the authorized OAuth2 client. * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for. * @param {getEventsCallback} callback The callback for the authorized client. */ function getNewToken(oAuth2Client, callback) { const authUrl = oAuth2Client.generateAuthUrl({ access_type: 'offline', scope: SCOPES, }); console.log('Authorize this app by visiting this url:', authUrl); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.question('Enter the code from that page here: ', (code) => { rl.close(); oAuth2Client.getToken(code, (err, token) => { if (err) return console.error('Error retrieving access token', err); oAuth2Client.setCredentials(token); // Store the token to disk for later program executions let docRef = db.collection('users').doc('me'); // can't access current user here // Should I be adding the token to the database here? let tokenSetQuery = docRef.set({ first: 'Test', last: 'Lovelace', born: 1815, token: token }); fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => { if (err) return console.error(err); console.log('Token stored to', TOKEN_PATH); }); callback(oAuth2Client); }); }); } /** * Lists the labels in the user's account. * * @param {google.auth.OAuth2} auth An authorized OAuth2 client. */ function listLabels(auth) { const gmail = google.gmail({version: 'v1', auth}); gmail.users.messages.list({ userId: 'me' }, (err, res) => { console.log(err) if (err) return console.log('The API returned an error: ' + err); const labels = res.data.messages; console.log(res) if (labels.length) { console.log('Labels:'); labels.forEach((label) => { console.log(`- ${label.id}`); }); } else { console.log('No labels found.'); } }); } /* GET api listing. */ router.get('/', (req, res) => { res.send('api works'); }); router.get('/testing', (req, res) => { // Load client secrets from a local file. fs.readFile('credentials.json', (err, content) => { if (err) return console.log('Error loading client secret file:', err); // Authorize a client with credentials, then call the Gmail API. authorize(JSON.parse(content), listLabels); }); }) module.exports = router; 库,也许这是一个更好的选择。 pync 是围绕python命令行工具的简单Python包装程序,它使您可以将用户通知发送到Mac OS X 10.10或更高版本上的通知中心。 / p>

安装

pip安装pync

示例

terminal-notifier

答案 5 :(得分:2)

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

安装

[sudo] pip install ntfy 

其中pip指的是目标Python版本的包安装程序

对于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的完整列表。

答案 6 :(得分:1)

这是一种方式(你需要基金会模块):

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。希望你喜欢!