本地运行正常,部署到Heroku后Selenium WebDriver异常退出问题
问题描述
基于Python、Django、Selenium开发的应用在本地运行无报错,但部署到Heroku线上环境后出现以下错误:
selenium.common.exceptions.WebDriverException: Message: Service /app/.wdm/drivers/chromedriver/linux64/106.0.5249/chromedriver unexpectedly exited. Status code was: 127
相关核心代码片段:
from selenium import webdriver from selenium.webdriver.chrome.options import Options from webdriver_manager.chrome import ChromeDriverManager def download(song, artist = None, play_after_downloading = True): # ... 省略其他代码 ... chromeOptions=Options() chromeOptions.add_experimental_option("prefs",{"download.default_directory":down_path}) chromeOptions.add_argument("--headless") driver = webdriver.Chrome(ChromeDriverManager(path=os.getcwd()).install(),options=chromeOptions) # ... 省略后续代码 ...
原因分析
- 依赖缺失:状态码127代表找不到依赖的执行文件。Heroku默认环境未安装Chrome浏览器,仅通过
webdriver-manager安装chromedriver无效——chromedriver必须配合对应版本的Chrome二进制文件才能运行。 - Headless模式参数不足:仅添加
--headless参数在Linux环境(Heroku基于Ubuntu)下不够,还需额外参数规避沙箱限制、内存不足等问题。 - 环境兼容问题:
os.startfile是Windows专属API,无法在Heroku的Linux环境执行;同时Heroku采用临时文件系统,下载的文件会随应用重启丢失。
解决办法
1. 添加Heroku Buildpacks
通过Heroku CLI或控制台添加两个buildpack,用于安装Chrome浏览器和对应版本的chromedriver:
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-google-chrome.git heroku buildpacks:add https://github.com/heroku/heroku-buildpack-chromedriver.git
注意保持Chrome的buildpack在前,确保依赖安装顺序正确。
2. 调整ChromeOptions配置
修改Chrome选项,补充Linux环境必需参数,并指定Chrome二进制文件路径:
chromeOptions = Options() chromeOptions.add_experimental_option("prefs", {"download.default_directory": down_path}) # 适配Linux环境的Headless参数 chromeOptions.add_argument("--headless=new") chromeOptions.add_argument("--no-sandbox") chromeOptions.add_argument("--disable-dev-shm-usage") chromeOptions.add_argument("--disable-gpu") # 指定Heroku上Chrome的安装路径 chromeOptions.binary_location = "/opt/google/chrome/chrome"
3. 初始化WebDriver的正确方式
通过buildpack安装的chromedriver会自动加入系统PATH,无需再用webdriver-manager下载,直接初始化:
# 替换原有的driver初始化代码 driver = webdriver.Chrome(options=chromeOptions)
4. 修复环境不兼容代码
- 移除或注释
os.startfile相关代码,该API仅支持Windows系统:# if play_after_downloading: # print("Song downloaded to :"+down_path) # print("playing") # os.startfile(down_path+"/"+song) # print(song) - 如需持久化下载文件,需配置外部存储服务(如AWS S3),因为Heroku的本地文件系统是临时的。
内容的提问来源于stack exchange,提问作者Nkosi Ncube
相关产品推荐
相关产品推荐

