屏蔽 Msys2 终端的 Python

前言

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 打开这个文件吧,把下面的函数粘贴进去。

  1. 在 Msys2 中可以通过 cygpath 命令查看 home 目录对应的 Windows 真实路径,用法是cygpath -w "<要查看的路径>",比如查看 home 目录的真实路径:
1
cygpath -w "${HOME}"
  1. 下面的函数我只在 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
# 处理 Msys2 的 Python 二进制文件
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

# 终端类型不是 Msys2 / MinGW / CygWin 时中断运行
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

# 在 Zsh 中屏蔽匹配不到文件的错误
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

# 恢复 Zsh 的原有配置
if [[ "${SHELL#/usr/bin/}" == "zsh" ]]; then
unsetopt NULL_GLOB
setopt ${zsh_options} 2> /dev/null
fi
}


# 屏蔽 Msys2 的 Python 二进制文件
block_msys2_python_bin() {
process_msys2_python_bin block
}


# 恢复 Msys2 的 Python 二进制文件
restore_msys2_python_bin() {
process_msys2_python_bin restore
}


block_msys2_python_bin # 直接调用命令, 这样在每次启动终端时都会运行这个命令, 将 Msys2 的 Python 屏蔽

粘贴后保存一下就行了。此时需要知道此时的终端用的是 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就可以再次屏蔽。


屏蔽 Msys2 终端的 Python
https://licyk.netlify.app/2025/06/26/block-msys2-python/
作者
licyk
发布于
2025年6月26日
许可协议