%%bash

echo -n "System Python version: "
python --version

%%bash

which python

%%bash

echo -n "Trying to import pip-install-test ... "
python -c "
try:
    import pip_install_test
except ModuleNotFoundError:
    print('pip-install-test is not installed')
else:
    print('pip-install-test is installed')"

%%bash

python -m venv /tmp/test_VE

%%bash

tree /tmp/test_VE | head
ls -l /tmp/test_VE/lib/python3.8/site-packages/

%%bash

echo "Activating VE"
source /tmp/test_VE/bin/activate

echo "Python's path"
which python
ls -l `which python`

echo "Python's version"
python --version

echo "Trying to import pip-install-test"
python -c "
try:
    import pip_install_test
except ModuleNotFoundError:
    print('pip-install-test is not installed')
else:
    print('pip-install-test is installed')"
    
echo "Installing pip-install-test"
pip install pip-install-test

echo "Trying to import pip-install-test"
python -c "
try:
    import pip_install_test
except ModuleNotFoundError:
    print('pip-install-test is not installed')
else:
    print('pip-install-test is installed')"

echo "Deactivating VE"
deactivate

echo "Python's path"
which python

echo "Python's version"
python --version

echo "Trying to import pip-install-test"
python -c "
try:
    import pip_install_test
except ModuleNotFoundError:
    print('pip-install-test is not installed')
else:
    print('pip-install-test is installed')"

echo "Deleting VE"
rm -rf /tmp/test_VE

"""
Explanation: <a href="https://colab.research.google.com/github/vicente-gonzalez-ruiz/YAPT/blob/master/01-hello_world/02-installation.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
Python installation
Contents

venv.
pyenv.

A word of warning
Python is usually installed in most modern OSs. However, it's a bad idea to develop (or even run) Pyhton code using the system Python because:

There are several versions of Python, and the one installed in your OS could not match your needs.
To install a package into your system Python, you have to run sudo pip install ..., probably affecting to other users/projects/already-installed-applications preferences. Moreover, probably you are going to install Python packages that are only need by you, and specifically in a single project.

A solution: Virtual Environments (VEs)
A VE provides a isolated runtime environment to develop Python code without interfering with the behaviour of other Python applications running on the same system.
There are several ways/tools to work with VEs. The covered here are:
1. Using the (only Python 3) module venv (try virtualenv if you need to use Python 2).
<a id='venv'></a>
venv
Python 3 ships venv, a Python module that allows to create, use and delele VEs. You should create (and use) so many different VEs as different combinations of incompatible Python projects (in terms of versions and packages dependencies) you are working on. The safest procedure is to use a different VE for each Python project.
, which you can run using python3 -m venv](https://stackoverflow.com/questions/41573587/what-is-the-difference-between-venv-pyvenv-pyenv-virtualenv-virtualenvwrappe).
A better option is to work with [Virtual Environments]. 
Creation
A VE are created with the command:
python -m venv name_of_the_VE
A directory named name_of_the_VE will be created in the current directory, with an structure to hold a copy of the last version of Python interpreter that you have installed in your system, the standard library, and various supporting files.
Activation
A previously created VE can be activated with:
source &lt;path_to_the_name_of_the_VE&gt;/bin/activate
Your prompt should have the prefix (name_of_the_VE).
Deactivation
A previously activated VE can be deactivated with:
deactivate
Deletion
Simply remove the name_of_the_VE structure.
Example
In this example we create, activate, use, deactivate, and delete a VE placed at /tmp/test_VE.
End of explanation
"""


%%bash

pyenv install 3.8.5

%%bash

pyenv versions

%%bash

pyenv which python

%%bash

pyenv global 3.8.5

%%bash

pyenv versions

%%bash

pyenv which python

%%bash

which python

%%bash

python --version

%%bash

echo "Trying to import pip-install-test"
python -c "
try:
    import pip_install_test
except:
    print('pip-install-test is not installed')
else:
    print('pip-install-test is installed')"

echo "Which pip I'm using?"
which pip

echo "Installing pip-install-test"
pip install pip-install-test

echo "Trying to import pip-install-test"
python -c "
try:
    import pip_install_test
except:
    print('pip-install-test is not installed')
else:
    print('pip-install-test is installed')"

%%bash

echo "Returning to System's Python"
pyenv global system
pyenv versions

echo "Pringing Python's version"
python --version

echo "Priting selected Python's version"
pyenv version

%%bash

pyenv uninstall -f 3.8.5

"""
Explanation: <a id='pyenv'></a>
Simple Python Version Management: pyenv
venv is useful if the version of Python installed in your system matches your needs. Howerver, when this does not happen, we can use a more sofisticated tool: pyenv. Basically, pyenv allows us to install multiple versions of Python in your user space, and specify the exact Python version you want in any moment.
<a id='pyenv-install'></a>
Install (in all Unixes, included OSX)
1. Run pyenv-installer
curl https://pyenv.run | bash
This has created the directory $HOME/.pyenv.
2. Add the following $HOME/.bashrc
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
3. Restart your shell
Run:
exec "$SHELL"
or just restart your terminal.
Uninstall
Simply, remove the lines added to the configuration file and run:
rm -rf $HOME/.pyenv
Listing pyenv commands
pyenv commands
Getting help
pyenv shell --help
Update the list of available Python versions
pyenv update
List available Python versions
pyenv install --list
Remember that in fact, Python is specification of a computer language. This list provides the different implementations avaiable thought pyenv. We can chose between:

CPython: the open-source reference implementation, writen in C and Python. Notice that CPython's versions are listed with the version number (without the cpython prefix). CPython defines the Python language specification.
ActivePython: a commercially supported Python for data science and machine learning.
Anaconda: a commercial Python implementation specialized in scientific computation.
IronPython: an open-source implementation integrated with the .NET Framework.
Jython: a Java-based implementation of Python that translates Python code to Java bytecode which is executed by the Java Virtual Machine.
MicroPython: an implementation of Python for the PyBoard.
Miniconda: the minimal expression of Anaconda.
PyPy: a faster (compared to CPython) implementation of Python based on the JIT (Just-In-Time) tecnology.
Stackless-Python: an extended version of CPython that allows to create Microthreads (also called Tasklets), a lighter thread than the created by the OS.

Install Python
See the oficial docs.
1. Prerequisites
Debians
See Common build problems if you are unable to install an environment.
Moreover, in order to have tkinter graphical interface avaiable, the tk-dev Linux package should have been installed.
sudo apt install tk-dev
OSX
TODO
Arch Linux
pacman -S gcc make
2. Download and compile
pyenv install -v 3.8.5
This will take a while (Python has to be download and compiled).
Uninstall
Run:
pyenv uninstall 3.8.5
or alternatively:
rm -rf $HOME/.pyenv/versions/3.8.5
<a id='pyenv-versions'></a>
Lists available Python versions
pyenv versions
The * indicates the Python version active currently.
Get the path to a tool provided by pyenv
pyenv which &lt;executable&gt;
Selecting the default Python version(s)
pyenv global &lt;version1&gt; [&lt;version2&gt;] ...
Set by $HOME/.pyenv/version (see command versions).
Selecting one or more Python versions for a project
pyenv local &lt;version1&gt; [&lt;version2&gt;]
Set by $HOME/.pyenv/.python-version. The local preference overrides the global one.
Selecting temporaly a Python version
pyenv shell &lt;version&gt;
Set by PYENV_VERSION environment variable. This Python version will be used while the current shell is alive. The shell preference overrides the local one.
Displays the currently active Python version
pyenv version
Example
In this example a version of Python is installed,  Be sure that pyenv has been installed (see pyenv install) before you run this notebook.
End of explanation
"""


%%bash

pyenv install 3.8.5

%%bash

pyenv virtualenv 3.8.5 socket_programming__385

%%bash

pyenv virtualenvs

%%bash

eval "$(pyenv init -)" # <- This should be in .bashrc

pyenv activate socket_programming__385
pyenv virtualenvs
pyenv deactivate

%%bash

pyenv virtualenvs

"""
Explanation: Creating a VE
pyenv virtualenv &lt;Python_version&gt; &lt;VE_name&gt;
VEs are stored in ~/.pyenv/versions/&lt;VE_name&gt;/.
Listing VEs
pyenv virtualenvs
Activating a VE
pyenv activate &lt;VE_name&gt;`
<!-- Now, `(<VE_name>)` should preceed your current prompt. -->

To activate a VE you must run virtualenv-initin your shell. You can run it directly from the shell with:
pyenv virtualenv-init
or you can include:
eval "$(pyenv virtualenv-init -)"
into the .bashrc file.
Deactivating a VE
pyenv deactivate
Delete a VE
pyenv uninstall &lt;VE_name&gt;
Example
Now, we create, activate, desativate, and remove a VE.
End of explanation
"""


%%bash

pyenv uninstall -f socket_programming__385

"""
Explanation: Notice that the * is missing.
End of explanation
"""


%%bash

echo "Showing versions of Python"
pyenv version

echo "Ensure the test VE does not exit"
pyenv uninstall -f my_python_project__system

echo "Create the test VE"
pyenv virtualenv 3.8.5 my_python_project__system

echo "Create and go into the test Python project"
rm -rf /tmp/my_python_project
mkdir /tmp/my_python_project
cd /tmp/my_python_project

echo "Hook the VE and the project"
pyenv local my_python_project__system

echo "Inside of the project the Python's version is ..."
python --version

echo "Outside of the project the Python's version is ..."
cd
python --version

"""
Explanation: Automatically activating and deactivating VEs
pyenv-virtualenv (running) automatically activate and deactivate the VE when you arrive to and leave a Python project that previously has been configured with:
pyenv local &lt;VE_name&gt;
Example
We configure a Python project to automatically activate a VE when we access to it.
End of explanation
"""


