如何使依赖Python的Emacs包(例如lsp-bridge)使用虚拟环境?

大部分的Linux发行版都会阻止使用pip全局安装Python包,因为Linux有包管理器。但是这会带来几个问题:

  1. 像Debian这种比较保守的仓库,所需的py包版本过低
  2. 很多py包依赖只是单独的某个插件使用,装在全局并不好
  3. 不同软件对某个py包有不同的版本要求

所以我想让Emacs包使用一个py虚拟环境。但同时我又想用Emacs写Python程序,开发环境又和包需要的虚拟环境不一样。我应该怎么配置。

配合

设置 lsp-bridge-python-command 即可。大部分需要 python 依赖的 emacs 包都支持配置专门的 python 路径。

我个人的想法是:所谓的Python虚拟环境只是一套环境变量,这个环境变量的设置脚本是<ENV_PATH>\bin\activate并不复杂,那么我完全可以用elisp脚本去把应该加的环境变量给setenv进去。这样用Emacs去调用的py脚本就有需要使用的环境变量了。

看lsp-bridge的wiki

您是指的“pyenv配置”这个词条吗?这个我之前看过了。我用的是Python3自带的venv,这个Python是系统自带的。

而pyenv是源码编译python。这些py的编译时的prefix是不同的,所以它们自然有不同的环境。这样看的话,源码编译py这个方案是最简单,最稳健的。因为环境变量可能会改变别的程序的行为。

1 个赞

pdm 有尝试过吗

直接将 python binary 的路径替换成你虚拟环境下的 python 绝对路径就行。

...venv/bin/python main.py

第三点用 pipx 或者 uv tool

我用 emacs 处理 python 虚拟环境的经验是这样的。

首先,我使用 uv 做包管理。因为 uv 添加一个新的包到环境里是使用的软链接,这样如果有两个环境使用了同一个包的同一个版本,不会把这个包所需要的空间算两遍。我在每一个环境里面都会下载 ruff 和 basedpyright 给 lsp-bridge使用。

然后,我写了一个函数在让 emacs 在执行了 counsel-projectile-switch-project 后自动切换 python 的虚拟环境。我写代码的时候就切换到一个专门的工作区来写。目前我没觉得这样操作有什么问题。

赞同这个想法,针对要求python做处理的包,我目前是先激活虚拟环境,再启动emacs, 如果能改成启动 emacs 时就能指定虚拟环境,后续它自己替换要用到的python命令就好了

很多人可能没理解楼上推荐的 envrc 在做什么。

首先 emacs 的环境变量是支持 buffer-local 的设置的,也就是说每个 buffer 都可以有自己的 $PATH,他们不需要继承全局的环境变量。但是在实践中这个 buffer-local 很多时候是很难起到你想要的效果的,因为大部分外部进程都有一个自己的独立 buffer,因此如果你想在 python-ts-hook 把环境变量改成 buffer local 的,那么你新开的 ipython 或者 pyright 之类的外部进程因为是自己独立的 buffer,所以它们并不会读取你的 python buffer 里的环境变量。

但是楼上推荐的 envrc 是用了另外一种做法,它是支持 project-wide 局部环境变量设定。其实实际上的实践就是对于每个新创建的 buffer,判断这个 buffer 的路径是否是在当前的 project 路径下,如果是的话,那么就把这个 buffer 的环境变量给改了。理论上这个方法是比使用同一套全局 path 变量然后不停的改来改去的方案更加优雅的去解决不同的项目想要开启不同的虚拟环境,启用不同的 python / pyright 路径这样一个问题的。

但是使用 envrc 这个包需要额外再装一个 binary direnv,因此我在思考有没有好的班服去继承这个思路,但是不需要再装 direnv。

2 个赞

你好,我在emacs中配合使用lsp-pyright和pdm过程中碰到了一个问题,一直无法得到很好的解决。过程是这样的,pdm中我只安装basedpyright,emacs配置中设置(setq lsp-pyright-langserver-command "basedpyright") basedpyright的绝对路径或相对路径都已配置过,lsp-pyright中的lsp-pyright-langserver-command检测不到basedpyright只会使用默认值pyright(如果pdm中只安装pyright,是能被lsp-pyright-langserver-command检测到的)。现在我的解决办法是在项目目录下.dir-locals.el文件中使用((python-mode . ((lsp-pyright-langserver-command . "~/Documents/mypackage/.venv/bin/basedpyright")))) basedpyright才能被lsp-pyright-langserver-command检测到。我不想使用 .dir-locals.el文件,有什么好的办法吗。

我是这么用的

1 个赞

首先你这个排版实在是看得头疼。

有一个点很奇怪,就是你dir-locals能设置成功,但是默认设置失败,建议你去掉dir-locals然后运行 lsp-pyright 的时候看看实际生效的 lsp-pyright-langserver-command 是多少

猜测可能是你的配置其他地方有设置这个变量