Windows任务计划程序运行虚拟环境Python脚本失败排查
我在Windows机器上有一个需在虚拟环境vir_env中运行的Python脚本,以满足依赖包要求。为此创建了如下批处理文件用于Task Scheduler:
call activate vir_env python "C:\Users\xxx\Documents\Anaconda\envs\vir_env\Scripts\script.py" call conda deactivate pause set /p id="Press enter when finished"
手动双击该批处理文件可成功执行,但通过Task Scheduler调度执行时,运行一段时间后失败。
手动运行时CMD显示:
DevTools listening on ws://127.0.0.1:61347/devtools/browser/d86ec8f2-7af2-4a2b-89f4-6c6f7025cc02
而通过任务计划程序运行时显示:
DevTools listening on ws://127.0.0.1:55329/devtools/browser/e8cd5010-6b41-4d35-a465-78a75e87a547
且出现如下错误栈:
DevTools listening on ws://127.0.0.1:55329/devtools/browser/e8cd5010-6b41-4d35-a465-78a75e87a547 Traceback (most recent call last): File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\Scripts\script.py", line 432, in <module> gv.save(deps, buffer, fmt='png') File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\holoviews\util\__init_.py", line 820, in save return renderer_obj.save(obj, filename, fmt=fmt, resources=resources, File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\holoviews\plotting\renderer.py", line 627, in save rendered = self_or_cls(plot, fmt) File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\holoviews\plotting\renderer.py", line 201 in __call__ data = self._figure_data(plot, fmt, **kwargs) File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\holoviews\plotting\bokeh\renderer.py", line 131, in _figure_data img = get_screenshot_as_png(plot.state, driver=state.webdriver) File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\bokeh\io\export.py", line 223, in get_screenshot_as_png web_driver.maximize_window() File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 737, in maximize_window self.execute(command, params) File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute self.error_handler.check_response(response) File "C:\Users\xxx\Documents\Anaconda\envs\vir_env\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.NoSuchWindowException: Message: Browsing context has been discarded
请问为何会出现这种情况?两次的DevTools监听链接不同,这是否是问题的潜在原因?
关于DevTools链接不同的问题
DevTools的监听端口和链接不同是正常现象——每次启动浏览器实例时,Chrome会随机分配一个新的调试端口,这不是导致任务调度失败的原因。
任务调度失败的核心原因
报错NoSuchWindowException: Browsing context has been discarded本质是Selenium无法找到对应的浏览器窗口,根源在于Windows任务计划程序的运行环境与手动运行的环境不一致:
桌面交互缺失
任务计划程序默认可能以无桌面交互的方式运行(尤其是勾选了"不管用户是否登录都要运行"时),而脚本通过Selenium调用Chrome生成截图需要可视化桌面会话。无桌面环境下,浏览器窗口无法正常初始化,很快被销毁,导致Selenium无法执行maximize_window()操作。虚拟环境激活异常
批处理中call activate vir_env可能在任务调度环境下无法找到conda激活脚本——任务计划的默认环境变量不包含conda路径,导致虚拟环境激活失败,后续依赖包(holoviews、bokeh、selenium)无法正常加载,间接引发浏览器初始化错误。权限不足
任务计划程序运行的用户权限低于手动运行权限,导致无法访问浏览器配置文件、临时目录,或无法启动Chrome进程。
解决步骤
1. 调整任务计划程序设置
- 常规选项卡:
- 勾选**"使用最高权限运行"**
- 若无需后台运行,选择**"只有在用户登录时才运行";若必须后台运行,勾选"不管用户是否登录都要运行"+"不存储密码",同时在设置选项卡取消勾选"如果任务运行时间超过XX小时就停止"**
- 操作选项卡:
- 在**"起始于(可选)"**中填入批处理文件所在目录,确保脚本能找到依赖路径
- 将
call activate vir_env替换为conda激活脚本的完整路径,例如:call C:\Users\xxx\anaconda3\Scripts\activate.bat vir_env(根据实际conda安装路径调整)
2. 修改Selenium浏览器配置
在Python脚本中添加无头模式和固定窗口大小,避免依赖桌面交互:
from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument("--headless=new") # 新版无头模式,支持完整浏览器功能 chrome_options.add_argument("--window-size=1920,1080") # 指定窗口大小,替代maximize_window chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("--no-sandbox") # 解决部分权限问题 driver = webdriver.Chrome(options=chrome_options)
同时确保Bokeh导出使用自定义driver:
from bokeh.io import export_png from bokeh.io.webdriver import webdriver_control # 替换默认临时driver with webdriver_control() as wc: wc.driver = driver export_png(plot, filename="output.png")
3. 优化批处理文件
去掉不需要的手动交互命令,确保脚本自动完成并退出:
@echo off call C:\Users\xxx\anaconda3\Scripts\activate.bat vir_env python "C:\Users\xxx\Documents\Anaconda\envs\vir_env\Scripts\script.py" call conda deactivate
内容的提问来源于stack exchange,提问作者pradeep chintapalli

