背景
原来安装了miniconda,备份了envs目录,卸载了miniconda后重新安装了miniforge,将envs目录恢复到miniforge的安装目录。在miniforge中可以看到原来的虚拟环境,也可以激活某个虚拟环境。但是在激活虚拟环境以后,无法使用该环境下安装过的wheel包。显示“无法执行:找不到需要的文件”。
(SenseVoice) latelinux@latelinux-laptop:~$ echo $PATH
:/home/latelinux/miniforge3/envs/SenseVoice/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
(SenseVoice) latelinux@latelinux-laptop:~/$ pip
bash: /home/latelinux/miniforge3/envs/SenseVoice/bin/pip: 无法执行:找不到需要的文件
原因
在<your-virtual-env-path>/bin
中,部分是可执行的二进制文件,例如python,而剩余的文件却是以脚本方式存在,例如pip(虽然它显示的是可执行文件,但它并不是一个二进制文件,而是一个脚本),以下是pip的内容,其中第一行的路径可以看到仍指向的旧的安装路径(miniconda3)。
(SenseVoice) latelinux@latelinux-laptop:~/miniforge3/envs/SenseVoice/bin$ cat ./pip
#!/home/latelinux/miniconda3/envs/SenseVoice/bin/python
# 这句话仍然指向miniconda3,而非miniforge3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())
解决
在所有虚拟环境的目录下,搜索脚本文件,并将其中的miniconda3更换为miniforge3,可以写个脚本完成。
import os
import re
def replace_keyword_in_file(file_path, old_keyword, new_keyword):
try:
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
if old_keyword in content:
new_content = content.replace(old_keyword, new_keyword)
with open(file_path, 'w', encoding='utf-8') as file:
file.write(new_content)
print(f"Updated {file_path}")
else:
print(f"No changes needed for {file_path}")
except UnicodeDecodeError:
print(f"Skipped binary file {file_path}")
def main():
base_dir = os.path.join('<your-miniforge3-installation-dir>','envs') # 请替换你自己miniforge3的安装目录
old_keyword = 'miniconda3'
new_keyword = 'miniforge3'
#遍历envs目录(base_dir 目录)下的所有子目录, 得到一个子目录列表(虚拟环境列表)后,遍历每个虚拟环境目录下的bin目录下的所有脚本文件
for root, dirs, files in os.walk(base_dir):
for dir in dirs:
bin_dir = os.path.join(root, dir, 'bin')
print(f'bin_dir: {bin_dir}')
if os.path.exists(bin_dir):
for file in os.listdir(bin_dir):
file_path = os.path.join(bin_dir, file)
# 判断文件为文件夹还是文件
if os.path.isdir(file_path):
continue
replace_keyword_in_file(file_path, old_keyword, new_keyword)
if __name__ == "__main__":
main()