我有一个 shell 函数(好吧,它是deactivate()
由 Python virtualenv 定义的函数),我想通过在执行之前或之后插入一些语句来修补它。我的目标是拥有一个新deactivate()
功能,它可以完成旧功能的功能,并且还可以做更多的事情。有办法做到这一点吗?
原始函数是从各个地方(各个 virtualenvs)动态定义的,因此在每个源处修改它并不是一个有吸引力的选择。
答案1
您可以创建一个比函数具有更高优先级的停用别名(如果足够的话)。因为您可以在之前运行命令,但在之后运行并不容易。
alias deactivate='before; deactivate'
或者简单地(更好)创建一个具有更简单名称的函数:
deact(){ [[ $somevar == true ]] && deactivate
[[ $othervar == admin ]] && sudo deactivate
}
或者任何你想实施的事情。是的,只会在定义的地方运行。它不是该词的替代品deactivate
,也不适用于其他用户。
唯一的方法是创建一个名为 的可执行程序deactivate
,但其优先级低于别名和函数。两者都需要未定义。
答案2
如果您的 shell 是bash
,zsh
或者ksh93
您可以利用typeset -f
内置函数,它会显示函数的源代码:
# usage patch_func funcname before after
function patch_func {
typeset nl=$'\n' lb={ src=`typeset -f "$1"` before=$2 after=$3
src="${src/$lb/$lb$nl $before$nl}"
src="${src%\}*}$nl $after$nl}"
eval "$src"
}
例子:
$ deactivate(){ echo -n "{$0}"; for i; do echo -n " {$i}"; done; echo; }
$ patch_func deactivate 'echo before' 'echo after'
$ typeset -f deactivate
deactivate ()
{
echo before;
echo -n "{$0}";
for i in "$@";
do
echo -n " {$i}";
done;
echo;
echo after
}
这当然是相当脆弱的。
答案3
虽然这个答案并不直接适用于virtualenv
使用 - 使用怎么样virtualenvwrapper
?它基本上是virtualenv
在类固醇上,负责环境管理。安装后,您将获得一组附加命令:
workon
在不带参数调用时列出所有可用环境,并在使用 env 名称作为参数调用时激活 env,例如workon myenv
激活 envmyenv
;mkvirtualenv myenv
创建一个新的环境myenv
;rmvirtualenv myenv
将其删除。
但还有更多 -virtualenvwrapper
定义了一组有用的钩子,您可以在其中实现自己的 envs 自定义逻辑,例如:
premkvirtualenv
当环境被创建但尚未激活时执行;postmkvirtualenv
当创建并激活 env 时执行;preactivate
当 env 激活被触发时执行;postactivate
当 env 被激活时执行;predeactivate
当触发 env 停用时执行;postdeactivate
当 env 被停用时执行;
还有很多。例如,我有一个postmkvirtualenv
安装ipython
在新环境中的钩子:
$ cat $VIRTUALENVWRAPPER_HOOK_DIR/postmkvirtualenv
#!/bin/bash
# This hook is sourced after a new virtualenv is activated.
env=$(basename "$VIRTUAL_ENV")
logger -s -t "($env)" "installing ipython ..."
"$VIRTUAL_ENV/bin/pip" install ipython --quiet
要为 env 停用定义附加逻辑,您必须编写一个自定义 bash 脚本并将其内容放置到$VIRTUALENVWRAPPER_HOOK_DIR/predeactivate
(如果您需要在 env 仍处于激活状态时运行您的东西)或$VIRTUALENVWRAPPER_HOOK_DIR/postdeactivate
(如果您需要停用 env运行自定义代码)。
以供参考:virtualenvwrapper
文档。
有关钩子的完整列表,请参阅每用户定制。