前言 Msys2 虽说好用,终端体验类似 Linux 终端,而且有个 pacman 包管理器方便装许多软件包,但总有一些坑在里面,比如 Msys2 中的 Python 调用优先级比原 Windows 系统中安装的 Python 优先级高(被这问题恶心的好久)。下面就介绍一种方法解决这个问题吧。
坑点 先来看看 Msys2 中的 Python 是在哪里坑的。一开始我在系统中安装了一个 Python 3.11,在 Msys2 终端中可以调用这个 Python。
1 2 $ python --version Python 3.11.8
这没什么问题,能正常调用已经安装的 Python 3.11。但在某一天为了使用 Hexo,用 pacman 命令安装了 NodeJS。
1 pacman -S mingw-w64-ucrt-x86_64-nodejs
安装完成后就去配置 Hexo 的东西了,但在安装 NodeJS 的过程中,pacman 把 Python 3.12 安装上了(不是很懂为什么 Python 要作为 NodeJS 的依赖)。
直到某一天我使用 Python 时就发现了不对劲,就用命令看了下 Python 版本。
1 2 $ python --version Python 3.12.11
欸,我不是安装的 Python 3.11 吗,怎么变成 Python 3.12 了?想了想,用which python
命令看了下 Python 调用的路径,发现居然在/ucrt64/bin/python
。
怎么会是呢,Msys2 怎么多给我整了个别的 Python,于是就用 pacman 查了一下,果然多了一个 Python。
1 2 3 $ pacman -Q | grep python mingw-w64-ucrt-x86_64-python 3.12.11-1 mingw-w64-ucrt-x86_64-python-packaging 25.0-1
解决思路 既然多装了 Python,那卸载掉就好了嘛,呃…
1 2 3 4 5 6 7 $ pacman -R mingw-w64-ucrt-x86_64-python 正在检查依赖关系... 错误:无法准备事务处理 (无法满足依赖关系) :: 删除 mingw-w64-ucrt-x86_64-python 破坏依赖 'mingw-w64-ucrt-x86_64-python' (mingw-w64-ucrt-x86_64-gdb 需要) :: 删除 mingw-w64-ucrt-x86_64-python 破坏依赖 'mingw-w64-ucrt-x86_64-python' (mingw-w64-ucrt-x86_64-glib2 需要) :: 删除 mingw-w64-ucrt-x86_64-python 破坏依赖 'mingw-w64-ucrt-x86_64-python' (mingw-w64-ucrt-x86_64-nodejs 需要) :: 删除 mingw-w64-ucrt-x86_64-python 破坏依赖 'mingw-w64-ucrt-x86_64-python' (mingw-w64-ucrt-x86_64-python-packaging 需要)
诶诶,卸不掉了。
按照 Shell 查找可执行文件的方式,会在 PATH 环境变量中按顺序查找 PATH 中的路径,找到可执行文件后立即执行,所以把系统中安装的 Python 3.11 的路径置于 PATH 环境变量内的最前面就行了吧,这个方法可以。
哦,另有一个办法,既然 Shell 可能会去找 Msys2 的 Python 可执行文件,那把可执行文件改个名让 Shell 找不到就好了嘛,这样问题就解决了。
给可执行文件改个名吧 写个自动执行的函数,把 Msys2 的 Python 找到,再重新命名,这样就不会再调用那 Msys2 的 Python 了。
打开终端后,用命令新建一个 sh 文件来编写函数吧。
1 touch "${HOME} /custom_cmd.sh"
运行后会在 /home/YourUserName 这个路径新建一个 custom_cmd.sh 文件(这里要注意一下,Msys2 的 home 目录是在安装这个终端的路径中的哦),用 Visual Studio Code 打开这个文件吧,把下面的函数粘贴进去。
在 Msys2 中可以通过 cygpath 命令查看 home 目录对应的 Windows 真实路径,用法是cygpath -w "<要查看的路径>"
,比如查看 home 目录的真实路径: 下面的函数我只在 Bash 和 Zsh 上测试过,如果 Msys2 用的是其他终端就不知道能不能用了,不能用的话用 AI 修一下就好了吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 process_msys2_python_bin () { local msys2_type_list=("clang64" "clangarm64" "mingw32" "mingw64" "ucrt64" "usr" ) local python_module_type_list=("python" "pip" "pythonw" ) local process_type="${*-block} " local search_prefix local zsh_options case "${OSTYPE} " in msys*|cygwin*|mingw*) ;; *) return 1 ;; esac case "${process_type} " in block) search_prefix="exe" ;; restore) search_prefix="exe.bak" ;; *) echo "未知操作类型" return 1 ;; esac if [[ "${SHELL#/usr/bin/} " == "zsh" ]]; then zsh_options=($(setopt )) setopt NULL_GLOB fi for bin_type in "${msys2_type_list[@]} " ; do for python_module_type in "${python_module_type_list[@]} " ; do for bin_path in "/${bin_type} /bin/${python_module_type} " *."${search_prefix} " ; do [[ ! -f "${bin_path} " ]] && continue case "${process_type} " in block) mv -f "${bin_path} " "${bin_path} .bak" ;; restore) mv -f "${bin_path} " "${bin_path%.bak} " ;; esac done done done if [[ "${SHELL#/usr/bin/} " == "zsh" ]]; then unsetopt NULL_GLOB setopt ${zsh_options} 2> /dev/null fi }block_msys2_python_bin () { process_msys2_python_bin block }restore_msys2_python_bin () { process_msys2_python_bin restore } block_msys2_python_bin
粘贴后保存一下就行了。此时需要知道此时的终端用的是 Bash,Zsh 或者是其他的终端解释器,就用下面的命令去查看吧。
1 echo "${SHELL#/usr/bin/} "
如果显示的是 bash,则配置文件是 .bashrc;如果显示的是 zsh,则配置文件是 .zshrc,显示的是其他的话就自己在 Google 上查找吧,应该都能查到的。一般配置文件都在 /home/YourUserName 这个路径里,没找到对应的配置文件就自己创建一个吧。
然后打开这个配置文件,在配置文件里写下初始化刚刚编写函数的文件的命令。
1 . "${HOME} /custom_cmd.sh"
保存一下,再重启一下终端。现在再试试检查 Python 是不是能调用系统中已安装的了。
1 2 $ python --version Python 3.11.8
这下正常了呢。如果想要恢复 Msys2 的 Python,运行一下restore_msys2_python_bin
命令就行了(不过下次启动终端时 custom_cmd.sh 会被执行一次,里面的block_msys2_python_bin
命令就会运行,把 Msys2 的 Python 屏蔽了),运行block_msys2_python_bin
就可以再次屏蔽。