使用 PyEnv 等配置 Emacs Python LSP

发布于 2025-01-26 16:42:43 字数 7367 浏览 8 评论 0

有许多文档描述了如何在 Emacs 中设置用于自动不全的 Python 语言服务器。然而,就我所看到的这些文档都缺少以下内容:

  • 如何在多个 Python 版本之间进行切换
  • 如何处理 Python 虚拟环境

我有一个简单但足够使用的工作流程,想与大家分享!

设置环境

用到的工具:

  • pyenv : 管理多个 python 版本
  • direnv : 处理项目相关的环境配置
  • venv : 在 Python 虚拟环境之间进行切换

设置 pyenv

官方提供了一个 自动安装脚本 。我不太喜欢使用它来安装,因为存在安全风险,但我也没有要检查这个安装脚本的意思:

  curl https://pyenv.run | bash

对于那些关注安全的人,请遵循其他 安装说明

Now, I'm using zsh as my shell. Let's set up the pyenv configuration in the ~/.zshenv : 目前,我使用 zsh 作为日常使用 shell. 让我们在 ~/.zshenv 中设置 pyenv 配置:

  export PATH="$HOME/.pyenv/bin:$PATH"
  eval "$(pyenv init -)"
  eval "$(pyenv virtualenv-init -)"

注意,我在 ~/.zshenv 而不是在 ~/.zshrc 中执行该操作。这是因为 ~/.zshrc 仅被交互式 shell 加载。你也可以把这段内容放到 ~/.zprofile 中。 你可以在这个 很棒的 stackoverflow 帖子 中了解到 zsh 各个启动文件的不同作用。

现在,如果我们打开一个新的终端,输入 whereis pyenv 你应该得到类似下面的内容:

kota@kota-ThinkPad-P1> whereis pyenv ~
pyenv: /home/kota/.pyenv/bin/pyenv

COMMENT 安装 direnv

嗯, direnv 也很容易安装,因为它是预先在 许多 Linux 发行版 中做成了可安装的包了。 在 Ubuntu 上:

  sudo apt install direnv

Then, we want to install the hooks into your shell . In my case, this is zsh , so in my .zshrc : 然后,我们 将钩子安装到 shell 中 。在本例中用的是 zsh ,所以我在 .zshrc 中加入:

  eval "$(direnv hook zsh)"

我们还将 pyenvvenv 配置添加到 ~/.config/direnv/direnvrc 中(抄自 direnv 的文档 ):

  use_pyenv() {
      unset PYENV_VERSION
      # Because each python version is prepended to the PATH, add them in reverse order
      for ((j ` $#; j >` 1; j--)); do
          local python_version=${!j}
          local pyenv_python=$(pyenv root)/versions/${python_version}/bin/python
          if [[ ! -x "$pyenv_python" ]]; then
              log_error "Error: $pyenv_python can't be executed."
              return 1
          fi

          unset PYTHONHOME
          local ve=$($pyenv_python -c "import pkgutil; print('venv' if pkgutil.find_loader('venv') else ('virtualenv' if pkgutil.find_loader('virtualenv') else ''))")

          case $ve in
              "venv")
                  VIRTUAL_ENV=$(direnv_layout_dir)/python-$python_version
                  export VIRTUAL_ENV
                  if [[ ! -d $VIRTUAL_ENV ]]; then
                      $pyenv_python -m venv "$VIRTUAL_ENV"
                  fi
                  PATH_add "$VIRTUAL_ENV"/bin
                  ;;
              "virtualenv")
                  layout_python "$pyenv_python"
                  ;;
              ,*)
                  log_error "Error: neither venv nor virtualenv are available to ${pyenv_python}."
                  return 1
                  ;;
          esac

          # e.g. Given "use pyenv 3.6.9 2.7.16", PYENV_VERSION becomes "3.6.9:2.7.16"
          [[ -z "$PYENV_VERSION" ]] && PYENV_VERSION`$python_version || PYENV_VERSION`"${python_version}:$PYENV_VERSION"
      done

      export PYENV_VERSION
  }

设置项目

我创建了一个非常简单的项目结构如下所示:

├── .envrc
├── foo
│ ├── app.py
│ ├── __init__.py
│ └── __main__.py
└── setup.py

这个应用程序要做的就是找出向量 (1,2,3) 的长度:

  import numpy as np

  def run():
  arr = np.array([1, 2, 3])
  print(np.linalg.norm(arr))

这里的关键是它使用了一个外部依赖项。

让我们再来看看 setup.py

  from setuptools import setup, find_packages
  from foo import __version__
  setup(
      name="foo",
      version=__version__,
      packages`find_packages(exclude`["tests"]),
      author="Kota Weaver",
      install_requires=[
          'numpy'
      ],
      extras_require={
          'dev': [
              'python-language-server[all]'
          ],
          'test': [
              'pytest', 'pyflakes'
          ]
      }
  )

注意,我在 dev 依赖中列出了 Python LSP 服务器。

现在让我们建立 Python 开发环境!首先是我 .envrc

export SIMENV_PYTHON=3.8.1

use pyenv $SIMENV_PYTHON

现在,如果我们进入项目目录,并执行 direnv allow ,应该就能够通过下面命令安装正确的 Python 版本:

  pyenv install $SIMENV_PYTHON

注意: 您可能需要安装以下依赖项: libffi-dev libssl-dev libreadline-dev libsqlite3-dev libbz2-dev

然后,离开并再次进入该目录,然后使用以下命令安装依赖项:

  pip install -e .['dev','test']

根据您的 shell,您也许需要使用  ~=~ ​ 来转义 [ ​ 和 ]=

确保 which python 显示的位置是正确的! 这允许我们使用下面命令运行程序使用:

kota@kota-ThinkPad-P1> python -m foo ~/foo
3.7416573867739413

设置 Emacs

现在,我们进入最重要的部分……,让我们配置 Emacs 来使用它做一些聪明的事情!

我使用 use-package , 我设置成如果没有安装则自动进行安装。我将这个设置在一个非常简单的 ~/.emacs.d/init.el 中,你可以随意引用:

  (setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
  ("marmalade" . "https://marmalade-repo.org/packages/")
  ("melpa" . "https://melpa.org/packages/")))
  (package-initialize)

  (when (not (package-installed-p 'use-package)) (package-refresh-contents) (package-install 'use-package))
  (require 'use-package)

  ; direnv mode allows automatic loading of direnv variables
  (use-package direnv
  :ensure t
  :config
  (direnv-mode))

  ; setup Emacs path from our ~/.zshenv
  (use-package exec-path-from-shell
  :ensure t
  :config
  (when (memq window-system '(mac ns x))
  (exec-path-from-shell-initialize)))

  ; we also should make sure we have flycheck installed
  (use-package flycheck
  :ensure t)

  ; Let's set up company! perhaps not necessary but this is what i like to use
  (use-package company
  :ensure t
  :config
  (setq company-idle-delay 0)
  (setq company-minimum-prefix-length 1))

  ; install lsp mode
  (use-package lsp-mode
  :ensure t
  :hook (python-mode . lsp-deferred)
  :commands (lsp lsp-deferred))

  ; let's add the lsp company backend
  (use-package company-lsp
  :ensure t
  :config
  (push 'company-lsp company-backends))

  ; also installs lsp as a dependency
  (use-package lsp-ui
  :ensure t
  :hook (lsp-mode . lsp-ui-mode))

下面是我机器上的一些截图(这是我的正常设置的截图,而不是上面精简版的截图,但应该有相同的功能:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

微暖i

暂无简介

文章
评论
28 人气
更多

推荐作者

冰魂雪魄

文章 0 评论 0

qq_Wl4Sbi

文章 0 评论 0

柳家齐

文章 0 评论 0

无法言说的痛

文章 0 评论 0

魄砕の薆

文章 0 评论 0

盗琴音

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文