はじまり

あれぇ? 戻っちゃったぞ

コイツが何かしらを捻じ曲げているな。
何が起きているのか
シェル上で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」の実行後に別途設定する方法がメンテしやすいと思います。
これで仮想環境を有効化しているかどうかを一目で確認出来るようになりました。開発体験が快適になりそうです。
おしまい

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

これで捻じ曲げ直したな。
以上になります!
コメント