
Sway 的 exec 指令默认在用户主目录(如 /home/theo)中执行命令,而非脚本所在路径,导致相对路径(如 data.json)读写失败,引发静默退出——这是自动化脚本在 Sway 中“看似运行但功能异常”的最常见原因。
sway 的 `exec` 指令默认在用户主目录(如 `/home/theo`)中执行命令,而非脚本所在路径,导致相对路径(如 `data.json`)读写失败,引发静默退出——这是自动化脚本在 sway 中“看似运行但功能异常”的最常见原因。
在 Sway 配置中使用 exec 执行自定义 Python 脚本时,一个极易被忽视却影响深远的关键点是:工作目录(working directory)不同。当你在终端中手动运行:
/home/theo/Repos/volumebar-dunst/bin/python /home/theo/Repos/volumebar-dunst/main.py raise 10%
Shell 会以当前终端所在路径(通常是你的项目根目录或 $HOME)为起点执行,而脚本内部通过 open('data.json', 'w') 写入文件时,实际路径为 ./data.json —— 即相对于当前工作目录。若你在 /home/theo/Repos/volumebar-dunst 下执行,data.json 就正确生成在该目录下。
但 Sway 的 exec 指令不继承终端环境的工作目录,而是默认在用户主目录(/home/theo)下启动进程。因此,当 Sway 执行:
bindsym XF86AudioRaiseVolume exec "/home/theo/Repos/volumebar-dunst/bin/python /home/theo/Repos/volumebar-dunst/main.py raise 10%"
Python 解释器虽能成功加载 main.py,但脚本运行时的当前工作目录是 /home/theo。此时 open('data.json', 'w') 尝试写入的是 /home/theo/data.json,而 load_data() 试图读取的也是该路径下的文件——但你的 data.json 实际位于 /home/theo/Repos/volumebar-dunst/。结果是:首次调用 data_exists() 因文件不存在而尝试创建新数据,但 save_data() 又因权限或路径逻辑问题(例如 os.path.exists('data.json') 返回 False,但后续 open(..., 'w') 失败)导致异常;由于脚本未捕获 I/O 异常且无日志输出,程序在 cli_command(...) 后静默崩溃,通知无法发送,仅音量调节等副作用(由 amixer 直接完成)仍生效。
✅ 正确解法:显式切换工作目录
修改 Sway 配置,使用 cd 确保脚本在预期路径下执行:
# sound bindsym XF86AudioRaiseVolume exec "cd /home/theo/Repos/volumebar-dunst && ./bin/python main.py raise 10%" bindsym XF86AudioLowerVolume exec "cd /home/theo/Repos/volumebar-dunst && ./bin/python main.py lower 10%" bindsym XF86AudioMute exec "cd /home/theo/Repos/volumebar-dunst && ./bin/python main.py mute"
? 提示:若 bin/python 是软链接或需绝对路径,建议改用 /home/theo/Repos/volumebar-dunst/bin/python;同时确保 main.py 具有可执行权限(chmod +x main.py),或统一用解释器显式调用。
? 进阶建议:增强脚本健壮性
为避免未来类似问题,可在 Python 脚本开头强制设定工作目录为脚本所在目录:
import os import sys # 将工作目录设为脚本所在目录(推荐放在 main() 之前) script_dir = os.path.dirname(os.path.abspath(__file__)) os.chdir(script_dir) # 后续所有相对路径均以此为准 data_path = 'data.json'
此外,添加基础异常处理与日志输出(如写入 ~/.volumebar-debug.log)能极大提升调试效率:
import logging
logging.basicConfig(
filename=os.path.expanduser('~/.volumebar-debug.log'),
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# 在关键步骤添加:
logging.info(f"Loading data from {data_path}")⚠️ 注意事项:
- Sway 的 exec 不支持 shell 特性(如管道、重定向、通配符),除非显式调用 sh -c "...";
- 避免在 exec 中使用 ~ 符号,应始终使用绝对路径(/home/theo/...);
- 若脚本依赖环境变量(如 PYTHONPATH),需在 exec 中显式导出或使用 env 命令封装。
总结:Sway 自动化不是“复制粘贴终端命令”即可运行,而是一场对执行上下文(工作目录、环境变量、shell 解析层级)的精准控制。理解并主动管理工作目录,是打通 CLI 与 Sway 自动化行为一致性的第一把钥匙。

















