Friday 15 January 2021

Troubleshooting virtualenvwrapper errors

It was my mistake that I did not track immediately the cause of the error that one day started appearing each time I'd open a new Terminal:

/usr/bin/python3: Error while finding module specification for 'virtualenvwrapper.hook_loader' (ModuleNotFoundError: No module named 'virtualenvwrapper')
virtualenvwrapper.sh: There was a problem running the initialization hooks.
If Python could not import the module virtualenvwrapper.hook_loader,
check that virtualenvwrapper has been installed for
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
and that PATH is
set properly.

virtualenvwrapper is, as its name says, a wrapper around virtualenv

When a new Terminal is opened, it starts a shell which sources the first of .bash_profile, .bash_login, .profile that exists and is readable. [bash - Why must I source .bashrc every time I open terminal for aliases to work? - Ask Different

In my case .bash_profile and .bash_login don't exist but .profile does and it sources ~/.bashrc:

$ cat ~/.profile 
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi


So I looked at ~/.bashrc and I found that some time in past I changed it to include some additional environment variables:

cat ~/.bashrc
...
# B.Komazec added:
# virtualenv and virtualenvwrapper
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh
...

Indeed, the error above was coming from virtualenvwrapper.sh, from function virtualenvwrapper_run_hook():

$ cat /usr/local/bin/virtualenvwrapper.sh
...
# Run the hooks
function virtualenvwrapper_run_hook {
    typeset hook_script
    typeset result

    hook_script="$(virtualenvwrapper_tempfile ${1}-hook)" || return 1

    # Use a subshell to run the python interpreter with hook_loader so
    # we can change the working directory. This avoids having the
    # Python 3 interpreter decide that its "prefix" is the virtualenv
    # if we happen to be inside the virtualenv when we start.
    ( \
        virtualenvwrapper_cd "$WORKON_HOME" &&
        "$VIRTUALENVWRAPPER_PYTHON" -m 'virtualenvwrapper.hook_loader' \
            ${HOOK_VERBOSE_OPTION:-} --script "$hook_script" "$@" \
    )
    result=$?

    if [ $result -eq 0 ]
    then
        if [ ! -f "$hook_script" ]
        then
            echo "ERROR: virtualenvwrapper_run_hook could not find temporary file $hook_script" 1>&2
            command \rm -f "$hook_script"
            return 2
        fi
        # cat "$hook_script"
        source "$hook_script"
    elif [ "${1}" = "initialize" ]
    then
        cat - 1>&2 <<EOF
virtualenvwrapper.sh: There was a problem running the initialization hooks.

If Python could not import the module virtualenvwrapper.hook_loader,
check that virtualenvwrapper has been installed for
VIRTUALENVWRAPPER_PYTHON=$VIRTUALENVWRAPPER_PYTHON and that PATH is
set properly.
EOF
    fi
    command \rm -f "$hook_script"
    return $result
}
...


I checked which packages are installed for pip3:

$ pip3 list

...but among them were neither virtualenv nor virtualenvwrapper. So I installed them:

$ sudo pip3 install virtualenv virtualenvwrapper 
Collecting virtualenv
  Downloading virtualenv-20.3.1-py2.py3-none-any.whl (5.7 MB)    
Collecting virtualenvwrapper
  Downloading virtualenvwrapper-4.8.4.tar.gz (334 kB)
Requirement already satisfied: six<2,>=1.9.0 in /usr/lib/python3/dist-packages (from virtualenv) (1.14.0)
Requirement already satisfied: appdirs<2,>=1.4.3 in /usr/lib/python3/dist-packages (from virtualenv) (1.4.3)
Requirement already satisfied: filelock<4,>=3.0.0 in /usr/lib/python3/dist-packages (from virtualenv) (3.0.12)
Collecting distlib<1,>=0.3.1
  Downloading distlib-0.3.1-py2.py3-none-any.whl (335 kB)
Collecting stevedore
  Downloading stevedore-3.3.0-py3-none-any.whl (49 kB)
Collecting virtualenv-clone
  Downloading virtualenv_clone-0.5.4-py2.py3-none-any.whl (6.6 kB)
Collecting pbr!=2.1.0,>=2.0.0
  Using cached pbr-5.5.1-py2.py3-none-any.whl (106 kB)
Building wheels for collected packages: virtualenvwrapper
  Building wheel for virtualenvwrapper (setup.py) ... done
  Created wheel for virtualenvwrapper: filename=virtualenvwrapper-4.8.4-py2.py3-none-any.whl size=24833 sha256=0e77420c4c5bd24518d388768cf102170bd8b0243fd3052fdbec24b01f3bb59a
  Stored in directory: /root/.cache/pip/wheels/47/15/3d/7a26eaf92e79f80a3df3ac5f8e0f0f5b7efdf24d313c594a44
Successfully built virtualenvwrapper
Installing collected packages: distlib, virtualenv, pbr, stevedore, virtualenv-clone, virtualenvwrapper
  Attempting uninstall: distlib
    Found existing installation: distlib 0.3.0
    Not uninstalling distlib at /usr/lib/python3/dist-packages, outside environment /usr
    Can't uninstall 'distlib'. No files were found to uninstall.
Successfully installed distlib-0.3.1 pbr-5.5.1 stevedore-3.3.0 virtualenv-20.3.1 virtualenv-clone-0.5.4 virtualenvwrapper-4.8.4


To verify that packages are installed indeed:

pip3 list
...
virtualenv             20.3.1              
virtualenv-clone       0.5.4               
virtualenvwrapper      4.8.4  
...

I opened a new Terminal and voila - the error is gone!

For a reference, my  Python paths are:

$ which python
/usr/bin/python

$ which python3
/usr/bin/python3


References


No comments: