6

我很好奇mkvirtualenv命令的底层发生了什么,所以我试图理解它是如何调用virtualenv的。

最简单的方法是弄清楚安装后virtualenv程序的位置以及安装后mkvirtualenv程序的位置。所以:-

Calvins-MacBook-Pro.local ttys006 Mon Apr 23 12:31:07 |~|
calvin$ which mkvirtualenv
Calvins-MacBook-Pro.local ttys006 Mon Apr 23 12:31:10 |~|
calvin$ which virtualenv
/opt/local/library/Frameworks/Python.framework/Versions/2.7/bin/virtualenv

所以我在这里看到的奇怪的事情是which mkvirtualenv没有给出任何结果。为什么?

进一步挖掘,在安装后的 virtualenvwrapper 目录中,我只看到 3 个 python 文件:-

Calvins-MacBook-Pro.local ttys004 Mon Apr 23 12:28:05 |/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/virtualenvwrapper|
calvin$ ls -la
total 88
drwxr-xr-x   8 root  wheel    272 Apr 13 15:07 .
drwxr-xr-x  29 root  wheel    986 Apr 15 00:55 ..
-rw-r--r--   1 root  wheel   5292 Apr 13 15:05 hook_loader.py
-rw-r--r--   1 root  wheel   4810 Apr 13 15:07 hook_loader.pyc
-rw-r--r--   1 root  wheel   1390 Apr 13 15:05 project.py
-rw-r--r--   1 root  wheel   2615 Apr 13 15:07 project.pyc
-rw-r--r--   1 root  wheel   7381 Apr 13 15:05 user_scripts.py
-rw-r--r--   1 root  wheel  11472 Apr 13 15:07 user_scripts.pyc

而且我认为现在在我的终端中可用的唯一原因mkvirtualenv是因为我添加了一个source/opt/local/library/Frameworks/Python.framework/Versions/2.7/bin/virtualenvwrapper.sh. 所以回答我之前提出的问题,这仅仅是因为它表示为一个 bash 函数并且在我的终端中可用,因为我在我的or文件mkvirtualenv中获取了 virtualenvwrapper.sh 。.bashrc.bash_profile

深入研究virtualenvwrapper.sh脚本,我明白了

# Create a new environment, in the WORKON_HOME.
#
# Usage: mkvirtualenv [options] ENVNAME
# (where the options are passed directly to virtualenv)
#
function mkvirtualenv {
    typeset -a in_args
    typeset -a out_args
    typeset -i i
    typeset tst
    typeset a
    typeset envname
    typeset requirements
    typeset packages

    in_args=( "$@" )

    if [ -n "$ZSH_VERSION" ]
    then
        i=1
        tst="-le"
    else
        i=0
        tst="-lt"
    fi
    while [ $i $tst $# ]
    do
        a="${in_args[$i]}"
        # echo "arg $i : $a"
        case "$a" in
            -a)
                i=$(( $i + 1 ));
                project="${in_args[$i]}";;
            -h)
                mkvirtualenv_help;
                return;;
            -i)
                i=$(( $i + 1 ));
                packages="$packages ${in_args[$i]}";;
            -r)
                i=$(( $i + 1 ));
                requirements="${in_args[$i]}";;
            *)
                if [ ${#out_args} -gt 0 ]
                then
                    out_args=( "${out_args[@]-}" "$a" )
                else
                    out_args=( "$a" )
                fi;;
        esac
        i=$(( $i + 1 ))
    done

    set -- "${out_args[@]}"

    eval "envname=\$$#"
    virtualenvwrapper_verify_workon_home || return 1
    virtualenvwrapper_verify_virtualenv || return 1
    (
        [ -n "$ZSH_VERSION" ] && setopt SH_WORD_SPLIT
        \cd "$WORKON_HOME" &&
        "$VIRTUALENVWRAPPER_VIRTUALENV" $VIRTUALENVWRAPPER_VIRTUALENV_ARGS "$@" &&
        [ -d "$WORKON_HOME/$envname" ] && \
            virtualenvwrapper_run_hook "pre_mkvirtualenv" "$envname"
    )
    typeset RC=$?
    [ $RC -ne 0 ] && return $RC

    # If they passed a help option or got an error from virtualenv,
    # the environment won't exist.  Use that to tell whether
    # we should switch to the environment and run the hook.
    [ ! -d "$WORKON_HOME/$envname" ] && return 0

    # If they gave us a project directory, set it up now
    # so the activate hooks can find it.
    if [ ! -z "$project" ]
    then
        setvirtualenvproject "$WORKON_HOME/$envname" "$project"
    fi

    # Now activate the new environment
    workon "$envname"

    if [ ! -z "$requirements" ]
    then
        pip install -r "$requirements"
    fi

    for a in $packages
    do
        pip install $a
    done

    virtualenvwrapper_run_hook "post_mkvirtualenv"
}

这是我还不明白的地方 - 我似乎virtualenv在这个 bash 函数中没有看到任何直接引用。那么这个 bash 函数究竟是如何mkvirtualenv将参数从命令行(例如mkvirtualenv -p python2.7 --no-site-packages mynewproject)传递给 pythonvirtualenv程序的呢?

4

1 回答 1

3

所以这是行之有效的方法。

(
    [ -n "$ZSH_VERSION" ] && setopt SH_WORD_SPLIT
    \cd "$WORKON_HOME" &&
    "$VIRTUALENVWRAPPER_VIRTUALENV" $VIRTUALENVWRAPPER_VIRTUALENV_ARGS "$@" &&
    [ -d "$WORKON_HOME/$envname" ] && \
        virtualenvwrapper_run_hook "pre_mkvirtualenv" "$envname"
)

$VIRTUALENVWRAPPER_VIRTUALENV实际上是当前virtualenv程序所在的位置。

在终端,

Calvins-MacBook-Pro.local ttys004 Mon Apr 23 13:24:14 |~|
calvin$ which $VIRTUALENVWRAPPER_VIRTUALENV
/opt/local/library/Frameworks/Python.framework/Versions/2.7/bin/virtualenv

谜团解开了。

于 2012-04-23T05:24:47.923 回答