You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS下cron定时任务运行Python脚本无法读取环境变量报错

问题根因

这不是权限问题,核心原因是cron定时任务的运行环境和你手动在终端/编辑器启动脚本的环境完全隔离:

  • macOS下cron执行任务时只会加载系统级的极简默认环境,默认运行shell为/bin/sh,不会主动加载zsh的用户级配置文件~/.zshenv
  • 你手动运行脚本时处于交互式zsh会话中,zsh会自动加载~/.zshenv内的配置,因此可以正常读取SMTP凭据;cron环境中不存在对应环境变量,os.getenv()读取到的返回值就是None,传入smtp.login()后尝试调用encode()方法就会触发你看到的AttributeError报错。
解决方案

以下三种方案任选其一即可,优先推荐前两种配置成本更低的方案:

  • 方案1:直接在crontab中声明环境变量(最稳定,不受shell配置影响)

    1. 终端执行crontab -e打开当前用户的定时任务配置
    2. 在你的定时任务行上方直接添加需要的环境变量配置,示例:
      EMAIL_ADDRESS="你的Gmail邮箱地址"
      EMAIL_PASSWORD="你的Gmail SMTP专用密码"
      # 原定时任务,注意写全python3和脚本的绝对路径
      */30 * * * * /usr/bin/python3 /Users/ourcore/Documents/Dev/site_monitor/monitor.py
      

    注意:Gmail SMTP登录需要使用开启两步验证后生成的应用专用密码,不能使用账号原登录密码。

  • 方案2:任务执行前主动加载zsh配置
    不需要额外迁移环境变量,直接修改cron任务的执行命令,指定通过zsh启动执行流,先加载~/.zshenv配置再运行脚本,和你手动在终端运行的环境完全一致,示例:

    */30 * * * * zsh -c 'source ~/.zshenv && /usr/bin/python3 /Users/ourcore/Documents/Dev/site_monitor/monitor.py'
    
  • 方案3:Python脚本内主动读取~/.zshenv配置
    如果不想修改crontab规则,可以在脚本读取环境变量的逻辑前,加一段主动解析~/.zshenv文件注入环境变量的代码,不依赖shell的配置加载逻辑,示例代码:

    import os
    from pathlib import Path
    
    # 主动加载~/.zshenv中的环境变量
    zshenv_file = Path.home() / ".zshenv"
    if zshenv_file.is_file():
        with open(zshenv_file, "r", encoding="utf-8") as f:
            for raw_line in f:
                line = raw_line.strip()
                if not line.startswith("export "):
                    continue
                # 解析export开头的配置行
                key, val = line[len("export "):].split("=", 1)
                # 去除值两侧的引号
                val = val.strip("\'\"")
                os.environ[key.strip()] = val
    
    # 后续原有读取变量的逻辑不需要修改
    EMAIL_ADDRESS = os.getenv("EMAIL_ADDRESS")
    EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")
    

内容的提问来源于stack exchange,提问作者Mario Parra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:21:13