Conda环境检测器
| 655 | |
| 656 | |
| 657 | class CondaDetector(_EnvironmentDetector): |
| 658 | """Conda环境检测器""" |
| 659 | |
| 660 | def __init__(self): |
| 661 | self.conda_paths = [] |
| 662 | |
| 663 | def find_conda_executable(self) -> List[str]: |
| 664 | # 预定义候选路径(保持原有逻辑) |
| 665 | conda_paths = [ |
| 666 | Path(os.path.expanduser("~/miniconda3")), |
| 667 | Path(os.path.expanduser("~/anaconda3")), |
| 668 | Path("/opt/conda"), |
| 669 | Path(os.getenv("CONDA_EXE", "")).resolve().parent.parent, # 从CONDA_EXE推导安装目录 |
| 670 | Path(os.getenv("CONDA_PREFIX", "")).resolve() # 从CONDA_EXE推导安装目录 |
| 671 | ] |
| 672 | |
| 673 | # 新增:从系统PATH查找 |
| 674 | for dir_path in self.now_env_path_list(): |
| 675 | p = Path(dir_path) |
| 676 | if p.is_dir(): |
| 677 | # 查找conda可执行文件(兼容符号链接) |
| 678 | conda_candidate = p / "conda" |
| 679 | if conda_candidate.exists(): |
| 680 | conda_paths.insert(0, conda_candidate.resolve().parent.parent) # 定位到conda安装根目录 |
| 681 | |
| 682 | res_list = [] |
| 683 | # 验证候选路径 |
| 684 | for path in conda_paths: |
| 685 | conda_bin = path / "condabin" / "conda" |
| 686 | if str(conda_bin) not in res_list and conda_bin.exists() and os.access(conda_bin, os.X_OK): |
| 687 | res_list.append(str(conda_bin)) |
| 688 | return res_list |
| 689 | |
| 690 | def detect(self) -> List[PythonEnvironment]: |
| 691 | if not self.conda_paths: |
| 692 | self.conda_paths = self.find_conda_executable() |
| 693 | |
| 694 | res_list = [] |
| 695 | for conda_path in self.conda_paths: |
| 696 | res_list.extend(self.detect_by_conda_bin(conda_path)) |
| 697 | return res_list |
| 698 | |
| 699 | @classmethod |
| 700 | def detect_by_conda_bin(cls, conda_path: str) -> List[PythonEnvironment]: |
| 701 | res_list = [] |
| 702 | try: |
| 703 | result = subprocess.run( |
| 704 | [conda_path, "env", "list", "--json"], |
| 705 | capture_output=True, text=True, check=True |
| 706 | ) |
| 707 | env_data = json.loads(result.stdout) |
| 708 | if not env_data.get("root_prefix", None): |
| 709 | root_prefix = Path(conda_path.split("/bin")[0]).resolve() |
| 710 | else: |
| 711 | root_prefix = Path(env_data["root_prefix"]).resolve() |
| 712 | # 解析环境名称和路径 |
| 713 | for env_spec in env_data["envs"]: |
| 714 | tmp_p = Path(env_spec).resolve() |
no outgoing calls
no test coverage detected