Bashプログラミング
 Computer >> コンピューター >  >> プログラミング >> Bashプログラミング

setV:Python仮想環境を簡単に管理できるBash関数

1年以上にわたり、setVは私のbash_scriptsプロジェクトの中にひっそりと眠っていましたが、ついに公開する時が来ました。setVは、virtualenvwrapperの代替として私が日常的に使用しているBash関数です。軽量ながら、Python仮想環境の管理に必要な基本機能を備えています。

setVの主な機能

  • デフォルトでPython 3を使用
  • 新しい仮想環境の作成
  • -p--python)オプションでカスタムPythonパスを指定した仮想環境の作成
  • 既存の仮想環境の削除
  • 既存のすべての仮想環境の一覧表示
  • Tab補完機能(仮想環境名を忘れてしまったときに便利)

インストール方法

setVをインストールするには、まずインストールスクリプトをダウンロードします。

curl https://gitlab.com/psachin/setV/raw/master/install.sh

ダウンロードしたスクリプトの内容をよく確認してから、実行してください。

sh ./install.sh

インストール時に、セットアップスクリプトが~/.bashrcまたは~/.bash_profileをsourceするよう求めてきます。この操作は必ず行ってください。これにより、setvコマンドがシェルで使えるようになります。

使い方

基本のコマンドはsetvです。以下に主な使用例を紹介します。

仮想環境を作成する

setv --new rango  # setv -n rango

# カスタムPythonバイナリのパスを指定する場合
setv --new --python /opt/python/python3 rango # setv -n -p /opt/python/python3 rango

既存の環境を有効化する

setv VIRTUAL_ENVIRONMENT_NAME

# 例
setv rango

すべての仮想環境を一覧表示する

setv --list
# または
setv [TAB] [TAB]

仮想環境を削除する

setv --delete rango

別の仮想環境へ切り替える

# 現在「rango」にいる状態から「tango」へ切り替える
setv tango

Tab補完

仮想環境の名前を完全には思い出せない場合でも、Bashと同様のTab補完が仮想環境名に対して機能します。setvと入力してTabキーを2回押すだけで、利用可能な仮想環境の一覧が表示されます。

プロジェクトへの参加

setVはGNU GPLv3ライセンスのオープンソースソフトウェアであり、コントリビューションを歓迎しています。詳しくは、GitLabリポジトリ内にあるsetVのREADMEの「Contribute」セクションをご覧ください。

setVスクリプトの全文

参考までに、setVスクリプトのソースコード全体を以下に示します。

#!/usr/bin/env bash
# setV - A Lightweight Python virtual environment manager.
# Author: Sachin (psachin) <iclcoolster@gmail.com>
# Author's URL: https://psachin.gitlab.io/about
#
# License: GNU GPL v3, See LICENSE file
#
# Configure(Optional):
# Set `SETV_VIRTUAL_DIR_PATH` value to your virtual environments
# directory-path. By default it is set to '~/virtualenvs/'
#
# Usage:
# Manual install: Added below line to your .bashrc or any local rc script():
# ---
# source /path/to/virtual.sh
# ---
#
# Now you can 'activate' the virtual environment by typing
# $ setv <YOUR VIRTUAL ENVIRONMENT NAME>
#
# For example:
# $ setv rango
#
# or type:
# setv [TAB] [TAB] (to list all virtual envs)
#
# To list all your virtual environments:
# $ setv --list
#
# To create new virtual environment:
# $ setv --new new_virtualenv_name
#
# To delete existing virtual environment:
# $ setv --delete existing_virtualenv_name
#
# To deactivate, type:
# $ deactivate

# Path to virtual environment directory
SETV_VIRTUAL_DIR_PATH="$HOME/virtualenvs/"
# Default python version to use. This decides whether to use `virtualenv` or `python3 -m venv`
SETV_PYTHON_VERSION=3 # Defaults to Python3
SETV_PY_PATH=$(which python${SETV_PYTHON_VERSION})

function _setvcomplete_()
{
# Bash-autocompletion.
# This ensures Tab-auto-completions work for virtual environment names.
local cmd="${1##*/}" # to handle command(s).
# Not necessary as such. 'setv' is the only command

local word=${COMP_WORDS[COMP_CWORD]} # Words thats being completed
local xpat='${word}' # Filter pattern. Include
# only words in variable '$names'
local names=$(ls -l "${SETV_VIRTUAL_DIR_PATH}" | egrep '^d' | awk -F " " '{print $NF}') # Virtual environment names

COMPREPLY=($(compgen -W "$names" -X "$xpat" -- "$word")) # compgen generates the results
}

function _setv_help_() {
# Echo help/usage message
echo "Usage: setv [OPTIONS] [NAME]"
echo Positional argument:
echo -e "NAME Activate virtual env."
echo Optional arguments:
echo -e "-l, --list List all Virtual Envs."
echo -e "-n, --new NAME Create a new Python Virtual Env."
echo -e "-d, --delete NAME Delete existing Python Virtual Env."
echo -e "-p, --python PATH Python binary path."
}

function _setv_custom_python_path()
{
if [ -f "${1}" ];
then
if [ "`expr $1 : '.*python\([2,3]\)'`" = "3" ];
then
SETV_PYTHON_VERSION=3
else
SETV_PYTHON_VERSION=2
fi
SETV_PY_PATH=${1}
_setv_create $2
else
echo "Error: Path ${1} does not exist!"
fi
}

function _setv_create()
{
# Creates new virtual environment if ran with -n|--new flag
if [ -z ${1} ];
then
echo "You need to pass virtual environment name"
_setv_help_
else
echo "Creating new virtual environment with the name: $1"

if [ ${SETV_PYTHON_VERSION} -eq 3 ];
then
${SETV_PY_PATH} -m venv ${SETV_VIRTUAL_DIR_PATH}${1}
else
virtualenv -p ${SETV_PY_PATH} ${SETV_VIRTUAL_DIR_PATH}${1}
fi

echo "You can now activate the Python virtual environment by typing: setv ${1}"
fi
}

function _setv_delete()
{
# Deletes virtual environment if ran with -d|--delete flag
# TODO: Refactor
if [ -z ${1} ];
then
echo "You need to pass virtual environment name"
_setv_help_
else
if [ -d ${SETV_VIRTUAL_DIR_PATH}${1} ];
then
read -p "Really delete this virtual environment(Y/N)? " yes_no
case $yes_no in
Y|y) rm -rvf ${SETV_VIRTUAL_DIR_PATH}${1};;
N|n) echo "Leaving the virtual environment as it is.";;
*) echo "You need to enter either Y/y or N/n"
esac
else
echo "Error: No virtual environment found by the name: ${1}"
fi
fi
}

function _setv_list()
{
# Lists all virtual environments if ran with -l|--list flag
echo -e "List of virtual environments you have under ${SETV_VIRTUAL_DIR_PATH}:\n"
for virt in $(ls -l "${SETV_VIRTUAL_DIR_PATH}" | egrep '^d' | awk -F " " '{print $NF}')
do
echo ${virt}
done
}

function setv() {
# Main function
if [ $# -eq 0 ];
then
_setv_help_
elif [ $# -le 3 ];
then
case "${1}" in
-n|--new) _setv_create ${2};;
-d|--delete) _setv_delete ${2};;
-l|--list) _setv_list;;
*) if [ -d ${SETV_VIRTUAL_DIR_PATH}${1} ];
then
# Activate the virtual environment
source ${SETV_VIRTUAL_DIR_PATH}${1}/bin/activate
else
# Else throw an error message
echo "Sorry, you don't have any virtual environment with the name: ${1}"
_setv_help_
fi
;;
esac
elif [ $# -le 5 ];
then
case "${2}" in
-p|--python) _setv_custom_python_path ${3} ${4};;
*) _setv_help_;;
esac
fi
}

# Calls bash-complete. The compgen command accepts most of the same
# options that complete does but it generates results rather than just
# storing the rules for future use.
complete -F _setvcomplete_ setv

仮想環境ディレクトリの場所を変更したい場合は、スクリプト内のSETV_VIRTUAL_DIR_PATHの値を任意のパスに書き換えるだけでOKです。デフォルトでは~/virtualenvs/が設定されています。

  1. Pythonのissubset()関数とは?部分集合の判定方法を実例付きで解説

    本記事では、Python標準ライブラリに用意されているissubset()関数の仕組みと使い方について詳しく解説します。 issubset()メソッドは、あるセット(集合)のすべての要素が、引数として渡した別のセットにも含まれている場合にブール値のTrueを返し、1つでも含まれていない要素があればFalseを返します。 下の図では、BはAの部分集合です。もしAとBが同一のセットであれば、両者は互いに部分集合の関係にあるといえます。つまり、両方のセットがまったく同じ要素を持っているということを意味します。 構文 <set 1>.issubset(<set 2>) 戻り値

  2. Pythonのintersection()関数とは?集合の共通要素(積集合)を求める方法

    この記事では、Pythonのセット(集合)に対して実行できるintersection()関数について詳しく解説します。数学における「積集合(インターセクション)」とは、2つの集合から共通する要素を見つけ出すことを指します。構文<セット名>.intersection(<セットa1>, <セットa2>, …)戻り値引数として渡されたすべての集合に共通する要素(積集合)が、新しいセットとして返されます。使用例set_1 = {t,u,t,o,r,i,a,l} set_2 = {p,o,i,n,t} set_3 = {t,u,t} # 2つの集合の積集合 print