mac自定义链接协议
在 macOS 上自定义一个链接协议(URL Scheme),并使其在访问时自动执行对应的脚本,可以通过以下步骤实现:
1. 创建 AppleScript 脚本
首先,使用 macOS 自带的 Script Editor 编写一个 AppleScript 脚本。这个脚本将作为处理自定义协议的核心逻辑。
例如,创建一个简单的脚本,当触发时会弹出一个对话框:
on open location this_URL
display dialog "你访问了自定义协议:" & this_URL
end open location保存脚本为应用程序格式:
- 在 Script Editor 中,选择 文件 > 导出。
- 将文件类型设置为 应用程序,并保存到合适的位置,比如
/Applications/MyCustomProtocol.app。
2. 修改应用程序的 Info.plist 文件
为了让 macOS 识别你的自定义协议,需要修改刚刚生成的应用程序的 Info.plist 文件。
-
右键点击生成的
.app文件,选择 显示包内容。 -
进入
Contents文件夹,找到并编辑Info.plist文件(可以使用 Xcode 或文本编辑器)。 -
添加以下内容以声明支持的 URL Scheme:
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLName</key> <string>com.example.myprotocol</string> <key>CFBundleURLSchemes</key> <array> <string>myprotocol</string> </array> </dict> </array>CFBundleURLName是协议的唯一标识符。CFBundleURLSchemes定义了协议名称,例如myprotocol://。
-
保存并关闭
Info.plist文件。
3. 注册协议
macOS 会自动识别已安装应用程序中声明的 URL Scheme。如果需要手动刷新 Launch Services 数据库,可以在终端运行以下命令:
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f /Applications/MyCustomProtocol.app这将确保系统能够识别你的自定义协议 。
4. 测试自定义协议
打开 Safari 或其他浏览器,在地址栏输入:
myprotocol://test
如果一切配置正确,系统会启动 MyCustomProtocol.app,并触发 AppleScript 脚本中的 open location 方法,显示对话框 。
5. 扩展:结合 Shell 脚本
如果你希望在触发协议时执行更复杂的任务(如运行 Shell 脚本),可以修改 AppleScript 脚本以调用外部脚本。例如:
on open location this_URL
do shell script "/path/to/your/script.sh " & quoted form of this_URL
end open location这样,当访问 myprotocol://example 时,script.sh 会被调用,并接收到 URL 参数 。
AppleScript执行python脚本
在 AppleScript 中执行 Python 脚本,可以通过调用系统命令(如 do shell script)来实现。以下是具体的实现步骤和示例代码:
1. 使用 do shell script 执行 Python 脚本
AppleScript 提供了 do shell script 命令,可以直接运行终端命令。通过该命令,可以调用 Python 解释器并执行指定的 Python 脚本文件。
示例代码
set pythonScriptPath to "/path/to/your_script.py"
do shell script "python3 " & quoted form of pythonScriptPathpythonScriptPath是 Python 脚本的绝对路径。quoted form of用于确保路径中的空格或特殊字符不会导致命令解析错误 。
2. 将 Python 脚本内容直接嵌入 AppleScript
如果 Python 脚本较短,可以直接将脚本内容嵌入 AppleScript 中,而无需单独保存为 .py 文件。
示例代码
set pythonCode to "
import sys
print('Hello from Python!')
"
do shell script "echo " & quoted form of pythonCode & " | python3"- 这里使用
echo将 Python 代码传递给python3解释器。 - 适合简单的脚本逻辑,但如果脚本较长,建议使用外部文件 。
3. 处理 Python 脚本的输出
AppleScript 可以捕获 Python 脚本的输出,并将其存储到变量中进行后续处理。
示例代码
set pythonScriptPath to "/path/to/your_script.py"
set scriptOutput to do shell script "python3 " & quoted form of pythonScriptPath
display dialog "Python 脚本输出:" & scriptOutputscriptOutput存储了 Python 脚本的标准输出。display dialog用于显示输出内容 。
4. 示例:结合 AppleScript 和 Python 实现功能
假设有一个 Python 脚本 example.py,其内容如下:
# example.py
import sys
def main():
print("Hello from Python!")
return 0
if __name__ == "__main__":
sys.exit(main())在 AppleScript 中调用该脚本并捕获输出:
set pythonScriptPath to "/path/to/example.py"
try
set scriptOutput to do shell script "python3 " & quoted form of pythonScriptPath
display dialog "Python 脚本输出:" & scriptOutput
on error errMsg
display dialog "执行 Python 脚本时出错:" & errMsg
end try以下是修改后的 AppleScript 脚本,将通过自定义协议获取到的参数 this_URL 传递给 Python 脚本,并执行该脚本:
修改后的 AppleScript 脚本
on open location this_URL
-- 定义 Python 脚本的路径
set pythonScriptPath to "/path/to/your_script.py"
-- 将 URL 参数传递给 Python 脚本
do shell script "python3 " & quoted form of pythonScriptPath & " " & quoted form of this_URL
-- 显示对话框以确认操作
display dialog "你访问了自定义协议:" & this_URL
end open location关键点解析
-
do shell script的使用- 使用
do shell script调用系统命令。 quoted form of确保路径和参数中的空格或特殊字符不会导致命令解析错误 。
- 使用
-
传递参数
this_URL是通过自定义协议传递的参数(例如myprotocol://example)。- 将
this_URL作为命令行参数传递给 Python 脚本。
-
Python 脚本路径
- 替换
/path/to/your_script.py为实际的 Python 脚本路径。
- 替换
-
对话框提示
- 使用
display dialog显示用户友好的提示信息 。
- 使用
修改后的脚本
#!/usr/bin/env python3
import sys
import os
import subprocess
from urllib.parse import unquote
def open_file(file_path):
# 检查文件是否存在
if not os.path.exists(file_path):
print(f"错误:文件 '{file_path}' 不存在。")
sys.exit(1)
# 使用 macOS 的 `open` 命令调用默认应用程序打开文件
try:
subprocess.run(["open", file_path], check=True)
print(f"文件 '{file_path}' 已使用默认应用程序打开。")
except subprocess.CalledProcessError as e:
print(f"错误:无法打开文件 '{file_path}'。详细信息:{e}")
sys.exit(1)
def extract_file_path(url):
# 提取 `anylink://` 后的文件路径
if not url.startswith("anylink://"):
print(f"错误:无效的协议格式。必须以 'anylink://' 开头。")
sys.exit(1)
# 去掉协议前缀
file_path = url[len("anylink://"):]
# 对 URL 编码的路径进行解码
file_path = unquote(file_path)
return file_path
if __name__ == "__main__":
# 检查是否提供了 URL 参数
if len(sys.argv) < 2:
print("错误:未提供参数。用法: python3 anylink.py <anylink://文件路径>")
sys.exit(1)
# 获取 URL 参数
url = sys.argv[1]
# 提取文件路径
file_path = extract_file_path(url)
# 调用函数打开文件
open_file(file_path)关键点解析
-
提取文件路径
- 使用字符串操作去掉
anylink://前缀。 - 使用
urllib.parse.unquote解码 URL 编码的路径(例如,将%20转换为空格)。
- 使用字符串操作去掉
-
检查协议格式
- 确保输入的 URL 以
anylink://开头。如果格式不正确,脚本会报错并退出。
- 确保输入的 URL 以
-
文件路径处理
- 提取的文件路径会被传递给
open_file函数,由其检查文件是否存在并调用open命令打开文件 。
- 提取的文件路径会被传递给
-
错误处理
- 如果文件不存在或
open命令执行失败,脚本会输出详细的错误信息并退出。
- 如果文件不存在或
运行流程
-
触发自定义协议
假设自定义协议为anylink:///Users/username/Documents/example.txt,当用户点击该链接时,AppleScript 将 URL 作为参数传递给 Python 脚本。 -
Python 脚本处理参数
- 脚本提取
anylink://后的文件路径。 - 解码 URL 编码的路径。
- 检查文件是否存在,并调用 macOS 的默认应用程序打开文件。
- 脚本提取
测试步骤
-
保存脚本
将上述代码保存为anylink.py,并确保其具有可执行权限:chmod +x anylink.py -
触发自定义协议
在浏览器中访问以下链接:anylink:///Users/username/Documents/example.txt或者通过 AppleScript 调用 Python 脚本:
do shell script "python3 /path/to/anylink.py 'anylink:///Users/username/Documents/example.txt'" -
验证结果
- 确保文件被成功打开。
- 检查终端输出,确认脚本的执行过程。
注意事项
-
URL 编码
如果文件路径中包含特殊字符(如空格、中文等),需要确保它们在 URL 中正确编码。例如,空格应编码为%20。 -
绝对路径
文件路径必须是绝对路径,否则可能导致文件找不到的错误 。 -
安全性
- 验证输入的 URL 格式,防止恶意输入。
- 确保脚本仅处理可信来源的参数。
通过以上修改,anylink.py 脚本可以成功提取 anylink:// 协议中的文件路径,并使用 macOS 的默认应用程序打开该文件 .
相关问题
我在命令行执行python是正常的,但是在脚本编辑器中执行
do shell script "python /Users/xiangyu/anylink/anylink.py 'anylink:///Users/xiangyu/Documents/pdftest/test.pdf'"会提示error "sh: python: command not found" number 127,若修改为python3就正常,这是为什么
这个问题的根本原因是 macOS 的 do shell script 命令在执行时,默认使用的是系统的 /bin/sh Shell 环境,而不是你通常在终端中使用的 Shell(例如 bash 或 zsh)。这种环境差异导致了以下问题:
1. Python 的路径问题
在 macOS 上,默认的 python 命令可能并未正确配置到系统路径中。具体原因如下:
- 在较新的 macOS 版本中,Apple 已经移除了系统自带的 Python 2,并且默认不再提供
python命令。 - 如果你安装了 Python 3(例如通过 Homebrew 或官方安装包),它通常会提供一个
python3命令,但不会自动创建python的符号链接。
因此,在终端中运行 python 可能正常,因为你的用户环境(如 .bashrc 或 .zshrc)中已经配置了别名或 PATH 环境变量,指向了正确的 Python 解释器。但在 do shell script 中,用户的 Shell 配置文件(如 .bashrc 或 .zshrc)不会被加载,导致系统找不到 python 命令。
2. 使用 python3 的原因
当你将命令改为 python3 时,系统能够找到 python3,因为它通常安装在标准路径(如 /usr/local/bin/python3 或 /opt/homebrew/bin/python3),并且这些路径是全局可用的。因此,do shell script "python3 ..." 能够正常工作。
解决方案
方法 1:明确指定 Python 解释器路径
为了避免依赖系统 PATH,可以直接在脚本中指定 Python 解释器的完整路径。例如:
do shell script "/usr/local/bin/python3 /Users/xiangyu/anylink/anylink.py 'anylink:///Users/xiangyu/Documents/pdftest/test.pdf'"你可以通过以下命令找到 Python 3 的完整路径:
which python3方法 2:为 python 创建符号链接
如果你希望继续使用 python 命令,可以手动创建一个符号链接,将 python 指向 python3。例如:
sudo ln -s /usr/local/bin/python3 /usr/local/bin/python这将使 python 和 python3 都指向同一个解释器。
方法 3:修改 AppleScript 脚本以加载用户环境
如果希望 do shell script 加载用户的 Shell 配置文件(如 .bashrc 或 .zshrc),可以在命令前添加 source 操作。例如:
do shell script "source ~/.zshrc; python /Users/xiangyu/anylink/anylink.py 'anylink:///Users/xiangyu/Documents/pdftest/test.pdf'"注意:这种方法需要确保你的 Shell 配置文件中正确设置了 python 的别名或 PATH。
总结
error "sh: python: command not found" 的原因是 do shell script 默认使用 /bin/sh 环境,而该环境中没有配置 python 命令。通过明确指定 Python 解释器路径、创建符号链接或加载用户环境,可以解决此问题 .