【Python】venvを使いながら環境変数PS1を設定してプロンプトを見やすくしたい

Code

はじまり

リサちゃん
リサちゃん

あれぇ? 戻っちゃったぞ

135ml
135ml

コイツが何かしらを捻じ曲げているな。

何が起きているのか

シェル上でBashの環境変数「PS1」をゴニョゴニョいじると、ターミナルにおける現在の状態(プロンプト)を見やすく表示することが可能です。

例えば下記の画像の1行目のような感じです。

しかし、Pythonの開発などで使用する「venv」による仮想環境を有効化したり無効化すると、このPS1の内容が書き換わってしまい、せっかく見やすく設定したPS1の内容が見づらい状態に、文字色が白色に戻ってしまいます。

そこで今回は、venv使用時の環境変数「PS1」の設定について色々やっていきます。

今回の設定に利用した「virtualenv」パッケージのバージョンは、20.28.1です。

PS1の内容の確認

まず、各々の状態における環境変数PS1の内容を確認します。

venvをアクティベートした時の環境変数PS1の内容。

PS1='\[\](.venv) \[\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ \[\]\[\]'

venvを非アクティベートした時の環境変数PS1の内容。

PS1='\[\]\[\]\[\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ \[\]\[\]\[\]'

そして、今回はこのような形式でPS1を設定して、ターミナルの状態を表示を見やすくしたいと思います。

export PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] $(_current_branch)\[\033[00m\]\[\033[01;35m\]\$\[\033[00m\] '

venv実行時に何が起きているのか

今回、venvを作成してアクティベートする時の実行コマンドはこんな感じにします。

python -m venv .venv
source .venv/bin/activate

「.venv/bin/activate」のファイルの中身はこんな感じになっていました。PS1を設定している部分が見つかったので、この設定に対して何かしてあげれば良さそうです。venvをactivateする時もdeactivateする時もdeactivate関数は実行されるみたいですね。

# This file must be used with "source bin/activate" *from bash*
# You cannot run it directly

deactivate () {
    # reset old environment variables
    if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then    # <--- deactivateする時に通る
        PATH="${_OLD_VIRTUAL_PATH:-}"
        export PATH
        unset _OLD_VIRTUAL_PATH
    fi
    if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
        PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
        export PYTHONHOME
        unset _OLD_VIRTUAL_PYTHONHOME
    fi

    # Call hash to forget past commands. Without forgetting
    # past commands the $PATH changes we made may not be respected
    hash -r 2> /dev/null

    if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
        PS1="${_OLD_VIRTUAL_PS1:-}"
        export PS1
        unset _OLD_VIRTUAL_PS1
    fi

    unset VIRTUAL_ENV
    unset VIRTUAL_ENV_PROMPT
    if [ ! "${1:-}" = "nondestructive" ] ; then
    # Self destruct!
        unset -f deactivate
    fi
}

# unset irrelevant variables
deactivate nondestructive

# on Windows, a path can contain colons and backslashes and has to be converted:
if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
    # transform D:\path\to\venv to /d/path/to/venv on MSYS
    # and to /cygdrive/d/path/to/venv on Cygwin
    export VIRTUAL_ENV=$(cygpath /home/masudamazudamasu/NotionSynchronizer/.venv)
else
    # use the path as-is
    export VIRTUAL_ENV=/home/masudamazudamasu/NotionSynchronizer/.venv
fi

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/"bin":$PATH"
export PATH

# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
    _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
    unset PYTHONHOME
fi

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
    _OLD_VIRTUAL_PS1="${PS1:-}"    # <--- activateする時に通る
    PS1='(.venv) '"${PS1:-}"
    export PS1
    VIRTUAL_ENV_PROMPT='(.venv) '
    export VIRTUAL_ENV_PROMPT
fi

# Call hash to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
hash -r 2> /dev/null

上記の「.venv/bin/activate」のファイルにおいて、どうやら「_OLD_VIRTUAL_PS1」というBash環境変数の中にvenvを有効化する前の「PS1」の内容が入るみたいです。

なので、今回は「edit-ps1-env」という関数を作って、「.venv/bin/activate」が終了した後に実行したいと思います。

function _current_branch() {
  _git_branch=$(git branch --show-current 2>/dev/null) && echo "[branch: $_git_branch] "
}

function edit-ps1-env() {
  _my_ps1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] \[\033[01;33m\]$(_current_branch)\[\033[00m\]\[\033[01;36m\]\$\[\033[00m\] '
  case ${1} in
    --activate | -a)
      export _OLD_VIRTUAL_PS1="$_my_ps1"
      _my_venv_dir='.venv'
      PS1="\[\033[01;31m\]($_my_venv_dir)\[\033[00m\] ""${_my_ps1:-}"
      return 0
      ;;
    --deactivate | -d)
      # nothing to do
      return 0
      ;;
    *)
      echo "[ERROR] invalid options: '${1}'"
      return 1
      ;;
  esac
}

そして、エイリアスを作成します。

alias py-ve='python -m venv .venv'
alias py-va='source .venv/bin/activate; edit-ps1-env -a;'
alias py-vd='deactivate; edit-ps1-env -d;'

この状態でコマンドを実行してみます。すると、venvの有効化および無効化の後の両方で、プロンプトの文字色が自分の設定したい状態になりました。

py-va
py-vd

まとめ

今回は、Pythonでvenvを利用する際に、Bashのプロンプトの表示色を保持するための設定方法を紹介しました。

sedを使って設定する方法も考えてみましたが、「.venv/bin/activate」のファイル内にある、venvのディレクトリ名が出現する場所が変わってしまうと設定が面倒なことになりそうでした。なので、「.venv/bin/activate」の実行後に別途設定する方法がメンテしやすいと思います。

これで仮想環境を有効化しているかどうかを一目で確認出来るようになりました。開発体験が快適になりそうです。

おしまい

リサちゃん
リサちゃん

よしよし、これでいいんだよ

135ml
135ml

これで捻じ曲げ直したな。

以上になります!

コメント

タイトルとURLをコピーしました