pythonのlinter&formatterを設定する

前回neovimに関連したpython環境を見直したが、ついでにlinterやformatterをちゃんと入れておくことにしたのでメモ

linterの設定

vim-lspにて表示するための設定はこちらを参考にして以下のようになった。
https://qiita.com/tk0miya/items/5a5beb2586c63792ce10

[[plugins]]
repo = 'mattn/vim-lsp-settings'
hook_add = '''
  let g:lsp_settings = {
  \  'pylsp-all': {
  \    'workspace_config': {
  \      'pylsp-all': {
  \        'configurationSources': ['flake8'],
  \        'plugins': {
  \          'pylsp_mypy': { 'enabled': 1 }
  \        }
  \      }
  \    }
  \  }
  \}
'''

configurationSourcesの設定を入れることでflake8がデフォルトで見に行く設定ファイルが読まれるようになる。

linterの設定ファイルは setup.cfg を利用。

[pycodestyle]
max-line-length = 119
exclude =
    .git
    __pychache__
    .tox
    venv*

[mypy]
ignore_missing_imports = True

[isort]
profile=black

ちなみに、最初以下のようにflake8が有効になるようplugin設定して動かしたのだが、その状態でもpycodestyleが有効になっておりflake8の設定は反映されなかった。

  \        'plugins': {
  \          'flake8': { 'enabled': 1 },
  \          'pycodestyle': { 'enabled': 0 },
  \        }

もともとflake8を使っていたというわけではないため、そのままpycodestyleを使うことにし、これ自体の原因は追ってない。

formatter導入

pipxを利用して独立した仮想環境に以下の2つを置いておくことにした

  • isort
  • black

pipxはアプリケーションを個別の仮想環境にインストールするためのもの。 ~/.local/pipx/venvs の下に各アプリケーション用の環境が作られ、cli~/.local/bin に置かれるためここのpathを通しておけばすべてを実行できる。
https://github.com/pypa/pipx

vim-lsp-settingsを使っているのでそちらの仮想環境にもisortはデフォルトで入っている。それに対して手動でsymlinkを貼ってもいいが、変更するときなど手間がかかりそうなのでこちらにいれてしまうことに。

また、vim上でこれらを実行しやすくするpluginもあるようだが、手動で実行するとしても

  • コミット前にやるくらいの頻度
    • black . という形で再帰的にすべてのファイルに適用可能
  • vim上から外部コマンド実行で十分
    • !black %

であるため特にpluginは入れなかった。

参考

https://zenn.dev/yhay81/articles/yhay81-202102-pythonlint https://qiita.com/tk0miya/items/5a5beb2586c63792ce10 https://scrapbox.io/vimemo/Vim%E3%81%A7_python%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E3%82%92%E6%95%B4%E3%81%88%E3%82%8B_vim-lsp_%E4%BD%BF%E7%94%A8

neovimのpython環境についてメモ

vim-lspによる補完がうまく効かない状態になっていた。補完が効かない問題自体はvenvの環境そのものがおかしくなっていたようで新しく作り直したら問題なかったのだが、その際に調べたことをせっかくなのでメモしておく。

手元の環境はこんな感じ

  • pyenvで入れたpython3.7.7
  • プロジェクト毎にvenvで仮想環境作成
  • neovim, pynvimはglobal環境にpipでインストール済み
  • vim-lsp, vim-lsp-settingsを利用

neovimのpython環境

neovimでpython3を使う場合は以下2つのpackageが入ったpython3をproviderとして設定する必要がある。

  • neovim
  • pynvim

g:python3_host_prog にpathを設定すればそのpython3が使われることになるが、設定しなかった場合はシステムのものやpyenvのものを探しに行く。私の環境ではpyenvを使っており、pyenv localで設定されたversionのグローバル環境が参照されていた。

この部分はneovim専用の仮想環境を用意してそれを使うように設定しておくのがよいみたいだが、私はそこまで頻繁にversionの変更をしてこなかったのでグローバル環境にneovim用の必要なpackageだけ入れて使っていた(せっかくなので今回この辺は仮想環境を見るように直しておこうと思う)

ここでの注意点としては、venvの環境をシェル上でactivateしてあったとしてもそちらの仮想環境は使われないこと。

activateしたvenv側にだけpynvimなどを入れ、グローバル環境には何も入れない状態だとcheckhealthで以下のようにエラーになる。

## Python 3 provider (optional)
  - INFO: pyenv: Path: /usr/local/Cellar/pyenv/2.0.7/libexec/pyenv
  - INFO: pyenv: $PYENV_ROOT is not set. Infer from `pyenv root`.
  - INFO: pyenv: Root: /Users/uj/.pyenv
  - INFO: `g:python3_host_prog` is not set.  Searching for python3 in the environment.
  - INFO: Executable: /Users/uj/.pyenv/versions/3.7.7/bin/python3
  - ERROR: Command error (job=18, exit code 1): `'/Users/uj/.pyenv/versions/3.7.7/bin/python3' -c 'import sys; sys.path = list(filter(lambda x: x != "", sys.path)); import
  neovim; print(neovim.__file__)'` (in '/Users/uj/test')
    stderr: Traceback (most recent call last):  File "<string>", line 1, in <module>ModuleNotFoundError: No module named 'neovim'
  - INFO: Python version: 3.7.7
  - INFO: pynvim version: unable to load neovim Python module
  - ERROR: pynvim is not installed.
    Error: unable to load neovim Python module
    - ADVICE:
      - Run in shell: /Users/uj/.pyenv/versions/3.7.7/bin/python3 -m pip install pynvim

## Python virtualenv
  - INFO: $VIRTUAL_ENV is set to: /Users/uj/test/venv
  - INFO: Python version: 3.7.7
  - OK: $VIRTUAL_ENV provides :!python.

ちなみに上記はneovim-0.5.0の出力。0.4.4だと仮想環境は見つかったがactivateされていない、みたいなwarningが出る状態だったため少し混乱した。

pylsのpython環境

vim-lsp-settingsを利用しているのでlsp serverは以下にインストールされている。

~/.local/share/vim-lsp-settings/servers/pyls-al

この下にvenvで専用の仮想環境が作られておりその環境でlsp serverが起動する。これだけだと自分のプロジェクトの仮想環境が読まれない感じだが、内部で使っているjediが VIRTUAL_ENV という環境変数に設定があればその環境のsite-packagesも読むようになっている模様。
https://github.com/palantir/python-language-server/issues/660#issuecomment-553284845
リンクが貼られているjediのコードは少し古いが、最新を確認しても同様の処理だった。

pyvenvを利用する場合の仮想環境設定用pluginであるvim-virtualenvでもactivateした上でVIRTUAL_ENVの値を設定してるのでそんな感じっぽい。
https://github.com/jmcantrell/vim-virtualenv/blob/3841e26/autoload/virtualenv.vim#L50-L55

venvの場合、VIRTUAL_ENVへの値設定は venv/bin/activate にて行われているためactivateしてあれば目的の環境のpathが設定されている。
https://github.com/python/cpython/blob/bb3e0c240bc60fe08d332ff5955d54197f79751c/Lib/venv/scripts/common/activate#L41-L42

pylsが起動するのはneovim起動時にpluginが読み込まれたときなので、activateしたシェル上でneovimを起動すれば問題ない。

ちなみにneovim上での環境変数の設定は以下で確認できる。

:py3 import os
:py3 print(os.environ)

想定どおりプロジェクト用仮想環境のpackageが読まれているかは、プロジェクト用のvenv側にだけ特定のpackageを入れて LspDefinition で定義へジャンプできるか否かで確認した。

まとめ

当初vim-virtualenvなど入れて参照先を調整したりする必要あるのかと思ったが、特別なことは必要なく以下の形で問題なかった。

  • python3のグローバル環境にneovim, pynvimを入れる
    • もしくはneovim専用の仮想環境を用意して g:python3_host_prog で設定する
  • シェル上で venv/bin/activate してからneovimを起動する

pylsのpython環境はvenvで作成されている状態であるため、メインのpythonのversionを上げた際にpyls側の環境と乖離してエラーなどの表示に食い違いが出てくるかもしれないことは頭の片隅に置いておこうと思う。

colaboratoryでapexのinstallに失敗する

タイトルの通りでapexのinstallに失敗したのでメモ。

実行したコマンドはこちら

!git clone https://github.com/NVIDIA/apex.git
!git checkout ebcd7f084bba96bdb0c3fdf396c3c6b02e745042 # 2021/09/18時点での最新
%cd apex
!pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./

エラーにかかわる部分の出力がこちら

 torch.__version__  = 1.9.0+cu102


    /tmp/pip-req-build-uufz822x/setup.py:67: UserWarning: Option --pyprof not specified. Not installing PyProf dependencies!
      warnings.warn("Option --pyprof not specified. Not installing PyProf dependencies!")

    Compiling cuda extensions with
    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2020 NVIDIA Corporation
    Built on Mon_Oct_12_20:09:46_PDT_2020
    Cuda compilation tools, release 11.1, V11.1.105
    Build cuda_11.1.TC455_06.29190527_0
    from /usr/local/cuda/bin

    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-req-build-uufz822x/setup.py", line 171, in <module>
        check_cuda_torch_binary_vs_bare_metal(torch.utils.cpp_extension.CUDA_HOME)
      File "/tmp/pip-req-build-uufz822x/setup.py", line 106, in check_cuda_torch_binary_vs_bare_metal
        "https://github.com/NVIDIA/apex/pull/323#discussion_r287021798.  "
    RuntimeError: Cuda extensions are being compiled with a version of Cuda that does not match the version used to compile Pytorch binaries.  Pytorch binaries were compiled with Cuda 10.2.
    In some cases, a minor-version mismatch will not cause later errors:  https://github.com/NVIDIA/apex/pull/323#discussion_r287021798.  You can try commenting out this check (at your own risk).
    Running setup.py install for apex ... error

colab上で使われるcudaが11.1だが、pytorchがcuda10.2でビルドされたものであるため失敗。ということでapex自体は特に関係なく、デフォルトで入ってるpytorchがなぜかcolab上で使われるcudaのバージョンと異なっているためだった。

ちなみにcudaとpytorchのバージョン確認方法はこちらの通り
https://qiita.com/ysit/items/a601cb59523cc1961556

!nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2020 NVIDIA Corporation
Built on Mon_Oct_12_20:09:46_PDT_2020
Cuda compilation tools, release 11.1, V11.1.105
Build cuda_11.1.TC455_06.29190527_0

!python -c 'import torch; print(torch.__version__) '
1.9.0+cu102

pytorchの公式ページからcuda11.1向けのインストール方法を確認してpip入れる
https://pytorch.org/

!pip3 install torch==1.9.0+cu111 torchvision==0.10.0+cu111 torchaudio==0.9.0 -f https://download.pytorch.org/whl/torch_stable.html

これでapexのインストールは成功するようになった。