You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

基于Python Subprocess模块在不同Anaconda环境中启动Python脚本的问题排查

问题:ArcPro环境中subprocess启动Anaconda环境脚本失败的差异排查与解决

背景

我需要在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启动的进程会继承它的所有环境变量(比如PYTHONPATHPATH),这些变量会让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

火山引擎 最新活动