从Python和launchd启动osascript

1 投票
1 回答
1095 浏览
提问于 2025-04-17 22:45

这是我这个小程序的主要内容

有一个Python脚本,它会检查某个文件夹里是否有新的电影文件,并相应地更新一个sqlite3数据库,这样就可以把文件排队等待处理。这个脚本每分钟运行一次,使用launchctl来启动。

还有另一个Python脚本,它负责实际处理文件,使用HandBrake的命令行界面来转换文件。同样也是每分钟运行一次,使用launchctl。

在第二个脚本中,一旦转换完成,我想启动一个AppleScript,将文件导入到iTunes,并添加一些特定的信息。

所以,流程是:新的电影文件在文件夹中 -> 文件被排队 -> 文件被转换 -> 文件被导入到iTunes。

我遇到的问题是关于AppleScript的部分。如果我通过终端运行我的第二个Python脚本(负责转换和导入的那个),一切都很顺利。文件被转换后,AppleScript会把它导入到iTunes。但如果是launchctl来启动这个脚本,似乎就跳过了AppleScript的部分。

这是Python中与AppleScript相关的代码

import subprocess, shlex
cmd = "/usr/bin/osascript /Users/alexis/Developer/Media/import_iTunes.scpt '{0}' ".format(file)
subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE)

还有AppleScript的部分(我为了简化去掉了一些内容)

on run argv
    set newTrackPath to posix file (item 1 of argv)
    tell application "iTunes"
        activate
        set newTrack to add newTrackPath
    end tell
end run

我尝试过使用subprocess.call(cmd)、os.system(cmd)和subprocess.Popen(cmd)。

问题似乎是,当这个Python脚本是通过launchctl启动时,无法从Python中启动osascript。

有没有人能解释一下或者提供解决办法?

谢谢

1 个回答

2

你想知道launchd是以哪个用户身份运行Python脚本的吧?我猜你是以当前用户的身份在运行它;如果不是,那你应该这样做。

你的shlex代码有点多余,而且不太安全(比如,当你尝试导入I Wanna Be Bobby's Girl.mp3时会发生什么)。直接把参数列表组装起来就行了。

你的Python代码没有等子进程完成,也没有检查它的返回代码,所以如果出现错误,你根本不会知道。你需要解决这个问题:如果你知道子进程出错的原因,排查问题会容易得多。

如果你不关心AppleScript的输出,可以直接使用check_call这个方便的函数,如果AppleScript失败,它会抛出一个异常:

subprocess.check_call(["/usr/bin/osascript", 
        "/Users/alexis/Developer/Media/import_iTunes.scpt", file])

(或者,如果你真的有理由直接使用Popen,并且为了“简单”省略了相关代码,麻烦把它展示出来,这样我们才能看到你到底在做什么。)

你可能还想调整一下你的launchd XML,这样你的Python脚本的错误输出就能写入一个文件,方便查看。

撰写回答