macで使用するPythonバージョンを切り替える

きっかけ

  • ずっとしようと思っていて、意外とすぐできなかったのでメモ
  • しかも2021.5中旬ごろから(最近・・・!)、pyenvのアップデートでwarningが出るようになったとのことなのでメモ
  • pyenvを使って切り替える方法を書いておく



1. macにpyenv をインストールする

$ brew install pyenv
  • brew を使います
  • brew ない方は、 brew をインストールしてください
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Homebrew

2. pyenv でインストール可能なPythonのバージョンを確認する

$ pyenv install --list

3. 自分がインストールしたいPythonバージョンを指定してインストールする

  • 今回は 3.9.5 をインストールする
$ pyenv install 3.9.5

4. 自分のmacにインストールされているPythonのバージョンを確認する

$ pyenv versions

5. 先ほどインストールした新しいPythonバージョンに切り替える

$ pyenv global 3.9.5

# この段階では python --version してもまだ切り替わっていないので続けて以下を実行する

$ eval "$(pyenv init -)"

eval "$(pyenv init -)" したら、↓のメッセージが出た

  • 2021年5月中旬ごろから出るようになったらしい
WARNING: `pyenv init -` no longer sets PATH.
Run `pyenv init` to see the necessary changes to make to your configuration

参考:https://zenn.dev/antyuntyun/articles/pyenv_warning_resolve

  • zsh使ってる方は vim ~/.zshrc などして .zshrc ファイルに、
  • bash使ってる方は vim ~/..bashrc して .bashrc ファイルに、
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init --path)"
fi

を追記します

  • 追記したらsource ~/.zshrc (zshの人)、 source ~/.bashrc (bashの人) を実行して↑で追記した設定をシェルに反映させます

参考: https://qiita.com/sinnyuu_alter/items/e85401d591a98c56431a

  • ここまで設定して、再度 eval "$(pyenv init -)" を再度実行すると何も表示されないはずです

6. Pythonのバージョンが切り替わっているか確認する

$ python --version

ここまでで完了です.

参考:https://qiita.com/Kohey222/items/19eb9b3cbcec9b176625

pytest.raisesでmatch使う時の注意点

調べるきっかけ

  • pytestでテストをしていて、例外発生時のメッセージが合っているはずなのにテストが通らなかった
  • 今までは通ってたのに、なぜかと思った時に、今までエラーメッセージには使っていなかった f文字列 を今回、使っているのが怪しいと思い調査

具体的に困ったところ

  • 例えば↓のようにf文字列を使用して例外メッセージを出しているとき
# テスト対象
# 引数が0より大きくないと例外を飛ばすようにする関数があったとする
def calc(self, a, b):
    
    if 0 < a and 0 < b: 
        return a/b
    
    # InvalidErrorは独自に定義したErrorクラス
    raise InvalidError(f'a={a} or b={b} is invalid.')
# テスト

import pytest

with pytest.raises(InvalidError, match='a=0 or b=2 is invalid.'):
    calc(0, 2)
  • ↑の書き方では、合っているのに、テストが通らない
  • 手元で出たエラーはこんな感じだった
AssertionError: Regex pattern '例外メッセージ' does not match '例外メッセージ'. 
Did you mean to `re.escape()` the regex?

regexってなに?

  • 日本語に略すと 正規表現 の意味

解決方法

  • エラーメッセージに書いてあるとおり、 re.escape() を使うとテストが通るようになる
# テスト(修正版)

import pytest

with pytest.raises(InvalidError, match=re.escape('a=0 or b=2 is invalid.')):
    calc(0, 2)
  • こちらを見て解決

  • raw文字列(バックスラッシュを文字として扱う)raw文字列使ってるのに、メッセージが一致しないっていう内容っぽい

公式にはなんとなく使ってくださいとの記載がある・・・

  • 公式ドキュメントにこんな文面が・・・(スクショ

    f:id:YukiMatsu88:20210601193932p:plain
    pytest公式ドキュメントから引用

  • 公式ドキュメントはこちら

  • 特殊文字を含む可能性がある文字列を使ってる時は、 re.escape正規表現を無効にしないといけないっぽい?

  • f文字列って特殊文字なのか・・何者なのか?と疑問が残るが、深追いせずにとりあえず今後気をつけることにする