基于Python Subprocess模块在不同Anaconda环境中启动Python脚本的问题排查
背景
我需要在ESRI ArcPro GUI中运行一个脚本工具,但ArcPro自带的Anaconda环境强制要求安装ArcPy包,而目标脚本的依赖包无法与ArcPy共存。因此采用双环境方案:用ArcPro默认环境将参数写入文本文件后,通过subprocess调用批处理文件,启动独立的Anaconda环境运行目标脚本。
当前实现
Python调用代码
subprocess.Popen("C:\\Windows\\System32\\cmd.exe C:\\Users\\RDCHLNRO\\AppData\\Local\\Continuum\\anaconda3\\Scripts\\__TESTFORARC.bat")
批处理文件内容
@set "_args1=%1" @set _args1_first=%_args1:~0,1% @set _args1_last=%_args1:~-1% @set _args1_first=%_args1_first:"=+% @set _args1_last=%_args1_last:"=+% @set _args1= @if "%_args1_first%"=="+" if NOT "%_args1_last%"=="+" ( @CALL "%~dp0..\condabin\conda.bat" activate @CALL conda activate myenv @CALL C:\Users\RDCHLNRO\AppData\Local\Continuum\anaconda3\envs\myenv\python.exe C:\Users\RDCHLNRO\Desktop\waves2021\cc_ARC.py @GOTO :End ) @REM This may work if there are spaces in anything in %* @CALL "%~dp0..\condabin\conda.bat" activate %* @CALL conda activate myenv @CALL C:\Users\RDCHLNRO\AppData\Local\Continuum\anaconda3\envs\myenv\python.exe C:\Users\RDCHLNRO\Desktop\waves2021\cc_ARC.py :End @set _args1_first= @set _args1_last=
错误现象
执行后弹出命令提示符,出现以下错误:
Traceback (most recent call last):
File "C:\Users\RDCHLNRO\AppData\Local\Continuum\anaconda3\Scripts\conda-script.py", line 11, in
from conda.cli import main
ModuleNotFoundError: No module named 'conda'
CommandNotFoundError: 'activate'
Traceback (most recent call last):
File "C:\Users\RDCHLNRO\Desktop\waves2021\cc_LZMST_ARC.py", line 5, in
import numpy as np
File "C:\Users\RDCHLNRO\AppData\Local\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\site-packages\numpy_init_.py", line 140, in
from . import core
File "C:\Users\RDCHLNRO\AppData\Local\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\site-packages\numpy\core_init_.py", line 101, in
from . import _internal
File "C:\Users\RDCHLNRO\AppData\Local\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\site-packages\numpy\core_internal.py", line 18, in
IS_PYPY = platform.python_implementation() == 'PyPy'
File "C:\Users\RDCHLNRO\AppData\Local\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\platform.py", line 1262, in python_implementation
return _sys_version()[0]
File "C:\Users\RDCHLNRO\AppData\Local\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\platform.py", line 1223, in _sys_version
repr(sys_version))
ValueError: failed to parse CPython sys.version: '3.7.10 (default, Feb 26 2021, 13:06:18) [MSC v.1916 64 bit (AMD64)]'
但直接从Windows开始菜单打开cmd并运行该批处理文件时,Anaconda环境可正常启动并运行脚本。
排查发现:sys.path差异
分别在两种终端执行python -m site,得到完全不同的sys.path结果:
正常终端(开始菜单启动)的sys.path
sys.path = [ 'C:\\Users\\RDCHLNRO', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\myenv\\python37.zip', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\myenv\\DLLs', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\myenv\\lib', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\myenv', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\myenv\\lib\\site-packages', ] USER_BASE: 'C:\\Users\\RDCHLNRO\\AppData\\Roaming\\Python' (doesn't exist) USER_SITE: 'C:\\Users\\RDCHLNRO\\AppData\\Roaming\\Python\\Python37\\site-packages' (doesn't exist) ENABLE_USER_SITE: True
ArcPro启动的终端的sys.path
sys.path = [ 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\myenv', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\Resources\\ArcPy', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\DLLs', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\Lib', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\Lib\\site-packages', 'c:\\users\\rdchlnro\\appdata\\local\\programs\\arcgis\\pro\\bin', 'c:\\users\\rdchlnro\\appdata\\local\\programs\\arcgis\\pro\\Resources\\ArcToolbox\\Scripts', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\myenv\\python37.zip', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\lib\\site-packages\\future-0.18.2-py3.7.egg', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\lib\\site-packages\\pytz-2020.1-py3.7.egg', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\lib\\site-packages\\pywin32_ctypes-0.2.0-py3.7.egg', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\lib\\site-packages\\pywin32security', 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Programs\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\lib\\site-packages\\sympy-1.5.1-py3.7.egg', ] USER_BASE: 'C:\\Users\\RDCHLNRO\\AppData\\Roaming\\Python' (doesn't exist) USER_SITE: 'C:\\Users\\RDCHLNRO\\AppData\\Roaming\\Python\\Python37\\site-packages' (doesn't exist) ENABLE_USER_SITE: True
可见ArcPro启动的终端将默认arcgispro-py3环境的路径注入到了sys.path中,导致包查找逻辑混乱。手动添加缺失路径后,又出现numpy的sys.version解析错误:
ValueError: failed to parse CPython sys.version: '3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 05:37:49) [MSC v.1916 64 bit (AMD64)]'
求助问题
为什么两个看似相同的cmd终端表现差异巨大?如何让ArcPro中subprocess启动的终端能正常运行目标脚本?
我之前也碰到过类似的ArcPro环境隔离问题,核心原因是ArcPro会给它启动的所有进程注入大量自定义环境变量和路径,直接干扰了Anaconda环境的正常初始化。下面是几个经过验证的解决思路:
1. 启动cmd时强制创建干净的环境
ArcPro启动的进程会继承它的所有环境变量(比如PYTHONPATH、PATH),这些变量会让conda无法正确加载自身模块,同时让Python优先查找ArcPro环境的包。可以通过以下两种方式规避:
方式A:用start命令启动全新cmd窗口
修改Python调用代码,让subprocess启动一个完全独立的cmd进程,避免继承ArcPro的环境:
import subprocess subprocess.Popen('start cmd /k "C:\\Users\\RDCHLNRO\\AppData\\Local\\Continuum\\anaconda3\\Scripts\\__TESTFORARC.bat"', shell=True)
方式B:手动构建干净的环境变量
只保留系统必要的环境变量,清空ArcPro注入的干扰项:
import subprocess import os clean_env = { 'SystemRoot': os.environ.get('SystemRoot'), 'PATH': f"{os.environ.get('SystemRoot')}\\system32;{os.environ.get('SystemRoot')}" } subprocess.Popen( 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Continuum\\anaconda3\\Scripts\\__TESTFORARC.bat', env=clean_env, shell=True )
2. 修改批处理文件,强制清理环境并初始化conda
在批处理开头先清空PYTHONPATH,避免ArcPro的路径污染,再初始化conda环境:
@echo off :: 清空PYTHONPATH,彻底隔离ArcPro的路径干扰 set PYTHONPATH= :: 初始化conda的核心环境 call "%~dp0..\condabin\conda.bat" activate :: 激活目标独立环境 call conda activate myenv :: 直接调用目标环境的Python运行脚本(用%CONDA_PREFIX%自动获取环境路径) call "%CONDA_PREFIX%\python.exe" "C:\Users\RDCHLNRO\Desktop\waves2021\cc_ARC.py" :: 可选:退出conda环境 call conda deactivate :End
3. 直接调用目标环境的Python,跳过conda activate
如果不想依赖conda的activate脚本,可以直接指定目标环境的Python路径,并手动设置必要的环境变量:
import subprocess import os env = os.environ.copy() # 清空PYTHONPATH,避免ArcPro路径干扰 env['PYTHONPATH'] = '' # 指定目标环境的路径 target_env_path = 'C:\\Users\\RDCHLNRO\\AppData\\Local\\Continuum\\anaconda3\\envs\\myenv' env['CONDA_PREFIX'] = target_env_path # 把目标环境的路径放到PATH最前面,确保优先使用目标环境的工具 env['PATH'] = f"{target_env_path}\\Scripts;{target_env_path};{env['PATH']}" # 直接调用目标环境的Python运行脚本 subprocess.Popen( [f"{target_env_path}\\python.exe", "C:\\Users\\RDCHLNRO\\Desktop\\waves2021\\cc_ARC.py"], env=env, shell=True )
终端差异的根本原因
开始菜单启动的cmd是干净的系统级进程,只继承系统默认的环境变量;而ArcPro启动的进程会继承ArcPro自身的所有环境变量,包括:
PYTHONPATH:指向ArcPy和默认arcgispro-py3环境的路径,导致Python优先查找ArcPro的包PATH:优先指向ArcPro的Python路径,导致conda无法找到自身的可执行文件
这些注入的变量破坏了Anaconda环境的初始化逻辑,同时导致不同环境的Python模块(比如platform.py和numpy)混用,最终出现版本不兼容的错误。
内容的提问来源于stack exchange,提问作者NO645




