article_image

本文成文较早,如今的 macOS,大概已经不再内置 Python,或起码没有 Python 2.7。请根据实际情况变通。

不论如何,如果相比其他的脚本语言,你更喜欢或更擅长 Python 的话,这一章番外篇就是为你准备的。暂时用不上 Python 的读者也不用丧气,本系列文章原计划中没有这部分内容,所以权当作附赠的吧。

为什么要用 Python

介绍 Python,当然不仅仅是因为“有读者需要”,毕竟这门语言若是用得上的人寥寥无几,我可能私下就回复掉,而不至于特意写一篇文章了。

**Python 是数据处理的利器。**工科、理科、乃至很多完全没有编程背景的文科人士1,都有用 Python 来处理数据的需求。

熟悉效率工具的读者,对 Python 应该也不陌生。

那么,在 Automator 中如何使用 Python 这一利器?出于通用性考虑,我将提供 Python2.7 和 Python3 两套模板(既然能坚持读到这里,相信你懂的,有些学校/公司至今抱着 2.7 版本不撒手),即便你并没有太专业的编程知识,也可以查一下自己在用的 Python 版本,然后套上模板完事儿。

两个基础模板

下面是 Python2/7 和 Python3 两种模板。

Python 2.7

2.7 版本的模板相对简单,和 Shell 脚本章节的设置非常相似:

  1. Shell 设置为 /usr/bin/python
  2. 输入作为 stdin
  3. 脚本模板间下方:
#!/usr/bin/env python

mport sys
#你的其他模块

or f in sys.stdin:
    #你的脚本
Alt text
Python2.7 模板

在这个模板里,环境变量、文件输入、批处理之类的都帮你收拾好了。不过 Python 有一点比较特殊,就是需要导入各种功能模块,所以把你的脚本搬进模板时也不要忘记把模块装上。

Python 3

想要在 Automator 直接使用 Python3 就麻烦了。一般我们在脚本编辑器里写 Python 代码时,只需要在开头申明一下环境变量就能调用 Python3,可惜在 Automator 里这不奏效。不信邪的话,你可以试试强制指定使用 Python3:

Alt text
不管怎么设置都是 Python2.7

很不幸,最后你发现拿在手里的还是 Python2.7。这是因为,我们已经指定了 Shell 为 /usr/bin/python,脚本里写啥都于事无补2。所以换个思路,不用 /usr/bin/python,直接通过 bash 调用 Python3 怎么样?

  1. 将 Shell 设置为 /bin/bash
  2. 将输入设为作为自变量
  3. 脚本如下:
runpy3 () {
/usr/local/bin/python3 << 'EOF' - "$@"

import sys
#你的其他模块

for f in sys.argv:
    #你的脚本
EOF
}

runpy3 "$@"
Alt text
Python3 模板

再来测试一下,终于看见 Python3 了。接下来的事儿交给你,把自己的脚本填进去吧。

Alt text
通过 bash 脚本成功调用 Python3

如何查看 Python 的运行结果

和使用 AppleScript/Shell 脚本时一样,我们也希望能看到 Python 的运行结果,而不是瞪着一只黑箱乞求它运行成功。最合适的方法还是在系统通知里显示运行的结果或状态提示。

我们照例来看两个例子,一个使用 Automator 自带的模块,一个利用 Python 脚本,简单和详细的要求都能满足。

简单版的大家都再熟悉不过了(如果你读过前两章的话),老规矩套上通知模块:

Alt text
简易版通知模板

进阶一些,还是用脚本。脚本方案实质上还是在借用 AppleScript,所以之前学的 macOS 通知模板知识照样能用。下面提供的模板已经解决了零零碎碎的工作,你只需要套用进自己的 Automator 动作,然后自定义两个地方:

  • 这里是通知内容:填进自己通知标题。可以把整行 "这里是通知内容" 换成脚本中出现的变量,具体的各位 Python 玩家请自行组合。
  • 这里是通知信息:填进通知信息。同样可以使用变量。
from subprocess import call

noti_title = "这里是通知内容"
noti_msg = "这里是通知信息"
noti_cmd = 'display notification \"' + \
    noti_msg + '\" with title \"' + noti_title +'\"'

call(["osascript", "-e", noti_cmd])

搞定。

Alt text
使用脚本来发送通知

实战:做一个 JSON 美化工具

说到 Python 脚本最适合的使用场景,可能 JSON 数据的处理就是第一个。

先别急着关网页,其实玩过 iOS 自动化的读者,多多少少都接触过 JSON——捷径里面常见的扒网页动作,往往就要出来网页返回来的,什么豆瓣电影数据、图片地址、视频网址都藏在里面。为什么要用“藏”这个说法呢?看看捷径返回来的 JSON 数据你就知道了。

Alt text
JSON 数据往往是一团糟

这样的数据看起来当然不方便,于是有人开发了一些网页版 JSON 格式化工具。其实也有离线使用的办法,马上来看看 Automator 是怎么解决的。

Alt text
Automator 美化前后的 JSON 数据

这回我们在 Automator 里使用 Python 2.7,Shell 选择 /usr/bin/python,传递输入作为自变量,脚本在配图之后奉上。

Alt text
美化 JSON 的工作流
import os
import sys
import json
from subprocess import call
from subprocess import Popen, PIPE

noti_title_error = "json parse error."
noti_title_nojson = "argv's length is 1, no json text input."
noti_msg_error = "请输入合法的 JSON"
noti_msg_nojson = "你输入的啥都不是啊!"
noti_cmd_error = 'display notification \"' + \
    noti_msg_error + '\" with title \"' + noti_title_error +'\"'
noti_cmd_nojson = 'display notification \"' + \
    noti_msg_nojson + '\" with title \"' + noti_title_nojson +'\"'
 
length = len(sys.argv)

if length > 1:
    try:
        cmd = 'curl -s '+str(sys.argv[1])
        search_result = os.popen(cmd)
        jsonObj = json.loads(search_result.read())
        formatJsonStr = json.dumps(jsonObj,indent=4,ensure_ascii=False,sort_keys=True)
 
        scpt = '''
            on run {clipboard_content}
                tell application "System Events"
                    set activeApp to name of first application process whose frontmost is true
                    activate
                    display dialog the ["JSON Formatted! Copy to clipboard? \n\n" & clipboard_content] buttons {"Copy", "No Thanks"} default button 1 cancel button 2
                end tell

                set result_button to button returned of result as string

                if result_button is "Copy" then
                    set the clipboard to clipboard_content
                    
                end if
            end run'''
        args = [formatJsonStr]

        p = Popen(['osascript', '-'] + args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        p.communicate(scpt)
    except Exception, e:
        call(["osascript", "-e", noti_cmd_error])
else :
    call(["osascript", "-e", noti_cmd_nojson])

运行时填入想要捣鼓的网页,Automator 就会弹出格式化好的 JSON 结果(如果太长的话可能会在屏幕上顶天立地)并询问你要不要拷贝到剪贴板。

Alt text
使用效果,网址我编的
注:网址我编的。

JSON 数据处理只是 Python 的各项特长之一,其他玩法还是留给更专业的玩家吧。


  1. 用 Python 的不一定非得是编程高手,比如部分学生也许只是处于课业需要.
  2. 那 Python2.7 的模板开头填环境有何用?的确没用,但这是写 Python 代码的标准。

author_avatar

Lawyer, macOS/iOS Automation Amateur