Adding python version and pyenv virtualenv name to bash prompt? - bash

I'm trying to achieve a PS1 that will output [3.6.5#BooksHerokuDjango ~]$
My .bashrc has this:
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
eval "$(pyenv virtualenv-init -)"
export PYENV_VIRTUALENV_DISABLE_PROMPT='1'
function __python_prompt {
version_number=`python -V | cut -d " " -f2-`
version_name=`pyenv version-name`
at='#'
python_prompt=$version_number$at$version_name
echo $python_prompt
}
PS1="[\$(__python_prompt) \W]\$ "
export PS1
I have the following pyenv versions:
[3.6.5#BooksHerokuDjango ~]$ pyenv versions
system
2.7.14
2.7.14/envs/HackerNewsHerokuDjango
3.2
3.2/envs/BlogHerokuDjango
3.6.5
3.6.5/envs/BooksHerokuDjango
3.6.5/envs/PortfolioDjango
BlogHerokuDjango
* BooksHerokuDjango (set by PYENV_VERSION environment variable)
HackerNewsHerokuDjango
PortfolioDjango
When I change the virtualenv like so:
[3.6.5#BooksHerokuDjango ~]$ pyenv activate HackerNewsHerokuDjango
Python 2.7.14
[#HackerNewsHerokuDjango ~]$
The PS1 doesn't output like this [2.7.14#HackerNewsHerokuDjango ~]$
But then I change the virtualenv again:
Python 2.7.14
[#HackerNewsHerokuDjango ~]$ pyenv activate PortfolioDjango
[3.6.5#PortfolioDjango ~]$
I get the PS1 output that I wanted. What am I doing wrong for it to be inconsistent?

Related

pyenv - environment "activated", but python and pip not found

I suppose there is something wrong with my bash init scripts (like .bashrc or .bash_profile). But let's start from beginning.
I can create and activate pyenv environment, but when I try to use python, I get error: -bash: python: command not found.
It looks like pyenv understands creation and swapping envorinments. I mean, it's probably not malformed. There is preview of my tries:
$ mkdir test-python-project
$ cd test-python-project/
$ pyenv versions
* system (set by /home/vagrant/.pyenv/version)
3.7.10
3.7.10/envs/k-pkb-env
$ pyenv virtualenv 3.7.10 test-env
Looking in links: /tmp/tmpkwojcc1e
Requirement already satisfied: setuptools in /home/vagrant/.pyenv/versions/3.7.10/envs/test-env/lib/python3.7/site-packages (47.1.0)
Requirement already satisfied: pip in /home/vagrant/.pyenv/versions/3.7.10/envs/test-env/lib/python3.7/site-packages (20.1.1)
$ pyenv activate test-env
pyenv-virtualenv: prompt changing will be removed from future release. configure export PYENV_VIRTUALENV_DISABLE_PROMPT=1 to simulate the behavior.
(test-env) $ python
-bash: python: command not found
(test-env) $ pyenv local test-env
(test-env) $ cd ..
(test-env) $ pyenv deactivate
$ cd test-python-project/
(test-env) $ python
-bash: python: command not found
(test-env) $ pip
-bash: pip: command not found
(test-env) $ pyenv version
test-env (set by /home/vagrant/Work/test-python-project/.python-version)
I'm not sure how to configure bash init scripts, because in pyenv readme they suggest using .profile, which I don't have.
So, there are my bash inits:
.bashrc
$ cat .bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]
then
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
.bash_profile
$ cat .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
# PyEnv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
Some additional information:
$PATH variable
$ echo $PATH
/home/vagrant/.pyenv/plugins/pyenv-virtualenv/shims:/home/vagrant/.pyenv/bin:/home/vagrant/.local/bin:/home/vagrant/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
It's a bit strange for me, because this additional paths added by pyenv doesn't seem to contain path to desired virtual environment:
$ ls /home/vagrant/.pyenv/plugins/pyenv-virtualenv/shims
activate deactivate
$ ls /home/vagrant/.pyenv/bin
pyenv
type python
$ type python
-bash: type: python: not found
which python
$ which python
/usr/bin/which: no python in (/home/vagrant/.pyenv/plugins/pyenv-virtualenv/shims:/home/vagrant/.pyenv/bin:/home/vagrant/.local/bin:/home/vagrant/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)
I tried also pyenv rehash, but also still no effect:
(test-env) [vagrant#centos test-python-project]$ pyenv rehash
(test-env) [vagrant#centos test-python-project]$ python
-bash: python: command not found
With some help from #Simba, I managed to have my configuration correct:
.bash_profile
# .bash_profile
# !!! ITS IMPORTANT THESE LINES MUST BE BEFORE . ~/.bashrc
# PyEnv - only path-related
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
# !!! ITS IMPORTANT THESE LINES ABOVE MUST BE BEFORE . ~/.bashrc
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
.bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]
then
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
# PyEnv - commands
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
Solution
READ THE PYENV GUIDE CAREFULLY.
You didn't follow pyenv's README guide correctly. The guide tells you put PATH related operation in .bash_profile or .profile. But eval "$(pyenv init -)" in .bashrc.
Move pyenv init script from .bash_profile to .bashrc.
# Put it in .bashrc
# PyEnv
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
Extended Reading
You bash shell is not a login shell. .bash_profile is not sourced at all, which skip pyenv init -.
Bash initialization
login mode:
/etc/profile
~/.bash_profile, ~/.bash_login, ~/.profile (only the first one that exists)
interactive non-login:
/etc/bash.bashrc (some Linux; not on Mac OS X)
~/.bashrc
non-interactive:
source file in $BASH_ENV
The default shell on Linux is a non-login, interactive shell. The default shell on macOS is a login, interactive shell.
There's also a detailed explanation about the shell startup by flowblok
Ref
Unix shell initialization from pyenv wiki
Shell startup scripts

export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl#1.1)"eval "$(rbenv init -)" not valid in this context: export path

I was trying to install ruby on my machine. I had to add this -
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl#1.1)"eval "$(rbenv init -)"
The error I get every time I open my terminal
/Users/akash/.zshrc:export:23: not valid in this context: export PATH
Rest of my .zshrc -
# The next line updates PATH for the Google Cloud SDK.
if [ -f '/Users/akash/Desktop/Projects/cheaplops/clear/google-cloud-sdk/path.zsh.inc' ]; then . '/Users/akash/Desktop/Projects/cheaplops/clear/google-cloud-sdk/path.zsh.inc'; fi
# The next line enables shell command completion for gcloud.
if [ -f '/Users/akash/Desktop/Projects/cheaplops/clear/google-cloud-sdk/completion.zsh.inc' ]; then . '/Users/akash/Desktop/Projects/cheaplops/clear/google-cloud-sdk/completion.zsh.inc'; fi
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/akash/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/Users/akash/anaconda3/etc/profile.d/conda.sh" ]; then
. "/Users/akash/anaconda3/etc/profile.d/conda.sh"
else
export PATH="/Users/akash/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl#1.1)"eval "$(rbenv init -)"
export PATH=${PATH}:/usr/local/mysql/bin
First check do you have openssl installed, the second part is for rbenv but first one is setting openssl so your software can use that specific version.
brew info openssl#1.1
See what it show will give you details or not installed. If not installed you have to install it. Then run following command to see you can see directory from brew for openssl.
brew --prefix openssl#1.1
If path is visible that mean all good. Now check do you have rbenv install? that is software to be installed before doing this.
brew install rbenv
Now I found one error in your whole line, as that line is actually creating export entry, but there is nothing to separate command eval from export, try following command.
export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl#1.1)"; eval "$(rbenv init -)"
If you notice before eval I added ; so one process complete and next can run. You are basically setting options --with-open... in a environment variable, and then you are running command of rbenv. You can use following lines to install ruby I took reference from rbenv discussion
RUBY_CONFIGURE_OPTS="--with-openssl-dir=/usr/local/opt/openssl"; rbenv install 2.3.8

How can I avoid typing the "source ~/.bash_profile" command in the terminal every time?

I just installed Anaconda. When I try to run a command, lets say conda --version, I get the following error message:
zsh: command not found: conda
When I type in:
source ~/.bash_profile
Everything works:
conda --version
conda 4.8.0
But I have to type the command every time I start the terminal.
My .bash_profile looks like this:
# added by Anaconda3 2019.10 installer
# >>> conda init >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$(CONDA_REPORT_ERRORS=false '/Users/myusername/opt/anaconda3/bin/conda' shell.bash hook 2> /dev/null)"
if [ $? -eq 0 ]; then
\eval "$__conda_setup"
else
if [ -f "/Users/myusername/opt/anaconda3/etc/profile.d/conda.sh" ]; then
. "/Users/myusername/opt/anaconda3/etc/profile.d/conda.sh"
CONDA_CHANGEPS1=false conda activate base
else
\export PATH="/Users/myusername/opt/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda init <<<
What can I do to fix this?
System: macOS
place source ~/.bash_profile into ~/.zsh
Bash loads .bash_profile during init, for zsh it’s .zsh
Default shell was changed from bash to zsh with macOS Catalina, so that’s why there is the problem.

macOS shell: JAVA_HOME is empty inside script

I have macOS 10.11.6. The JAVA_HOME is set in the .bash_profile as
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
export PATH=$JAVA_HOME/bin:$PATH
From command line, I can see it
>echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home
But, the JAVA_HOME is empty, when I run the following script
#!/bin/sh
SHELL=/bin/sh
export SHELL
echo $JAVA_HOME
if [ -n "$JAVA_HOME" ]; then
#do something
else
echo JAVA_HOME is empty
fi
Even if I use #!/bin/bash in my script, the JAVA_HOME is still empty.
TL;DR
Depending on how you run your scripts, you may need to put your exports into ~/.bashrc for interative shells, or directly into your script or crontab so that it doesn't rely on exports from your user's shell.
Bash Startup Files
Simplistically, the ~/.bash_profile script is sourced for login shells (e.g. /bin/bash -l), while the ~/.bashrc file is sourced for interactive shell (e.g. /bin/bash -i). It's actually a bit more complicated than that, but the above should get you pointed in the right direction.
See Also
https://www.gnu.org/software/bash/manual/html_node/Invoking-Bash.html#Invoking-Bash
https://www.freebsd.org/cgi/man.cgi?query=bash#INVOCATION
man 1 bash
I configure mine like this:
# configure Java http://www.jenv.be/
# install Java: brew cask install java, brew cask install java7
# set global default: setJavaGlobal 1.7, jenv global 1.7
# set local folder default: jenv local 1.8
#
JENV_HOME=$HOME/.jenv
export PATH=.:$PATH:$JENV_HOME/bin
eval "$(jenv init -)"
export JAVA_HOME="$HOME/.jenv/versions/`jenv version-name`"
alias jenv_set_java_home='export JAVA_HOME="$HOME/.jenv/versions/`jenv version-name`"'
And some related shell methods I use in my .bash_profile :
setJavaGlobal() {
jenv global $1;
jenv_set_java_home
echoJavaSetup
}
setJavaLocal() {
jenv local $1;
jenv_set_java_home
echoJavaSetup
}
echoJavaSetup() {
echo --------------------
echo NEW JAVA SETUP:
echo " PATH: $PATH"
export JAVA_VERSION=`java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'`
echo " JAVA: $JAVA_VERSION, $JAVA_HOME"
jenv versions
echo --------------------
}
removeJavaLocal() {
rm -rf ./.java-version
}
showJava() {
echo --------------------
echo EXISTING JAVA SETUP:
echo " PATH: $PATH"
export JAVA_VERSION=`java -version 2>&1 >/dev/null | grep 'java version' | awk '{print $3}'`
echo " JAVA: $JAVA_VERSION, $JAVA_HOME"
jenv versions
if [ -f ./.java-version ]; then
echo "Using Java LOCAL DEFAULT. Not using global default! Run command 'removeJavaLocal' to change to global default."
fi
echo --------------------
}

How to pip install into a virtualenv via a bash install script?

I recently tried to automate the setup of an Ubuntu VM with a bash script (I am new to bash scripting).
The issue is that the way I set it up, it doesn't work. Particularly the mkvirtualenv and workon commands don't work in the bash script. How do I create a virtualenv in a bash script with passing it a variable and then install into the virtualenv via pip?
#!/bin/bash
VENV_NAME='name_of_virtualenv'
#Setting up virtualenv
mkdir --mode=770 /var/virtualenvs
chown -R www-data:www-edit /var/virtualenvs
chmod 771 /var/virtualenvs
echo '# virtualenv and virtualwrapper' >> ~/.bashrc
echo ' export VIRTUALENV_USE_DISTRIBUTE=1' >> ~/.bashrc # <-- Always use pip/distribute
echo ' export WORKON_HOME=/var/virtualenvs' >> ~/.bashrc
echo ' source /usr/local/bin/virtualenvwrapper.sh' >> ~/.bashrc
echo ' export PIP_VIRTUALENV_BASE=$WORKON_HOME' >> ~/.bashrc
echo ' export PIP_RESPECT_VIRTUALENV=true' >> ~/.bashrc
source ~/.bashrc
mkvirtualenv --distribute '{VENV_NAME}'
workon {VENV_NAME}
pip install psycopg2
pip install --upgrade PIL
You missing dollar before the call, also did not see an export for VENV_NAME
export VIRTUALENV_USE_DISTRIBUTE=1
echo {VIRTUALENV_USE_DISTRIBUTE}
{VIRTUALENV_USE_DISTRIBUTE}
echo ${VIRTUALENV_USE_DISTRIBUTE}
1
Unsure why you need to export out to bashrc and from the looks of it each time you run it, it would add the same exports to bashrc which will end up with a larger and larger bashrc file each time
Why not just make them local variables like
VIRTUALENV_USE_DISTRIBUTE=1
workon $VIRTUALENV_USE_DISTRIBUTE

Resources