{"id":228,"date":"2023-12-21T22:56:26","date_gmt":"2023-12-21T22:56:26","guid":{"rendered":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/?p=228"},"modified":"2026-04-23T14:23:40","modified_gmt":"2026-04-23T13:23:40","slug":"safely-installing-python-applications-and-managing-additional-python-versions","status":"publish","type":"post","link":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/2023\/12\/21\/safely-installing-python-applications-and-managing-additional-python-versions\/","title":{"rendered":"Safely installing Python applications and managing additional Python versions"},"content":{"rendered":"\n<p>NUIT sometimes see University Ubuntu systems where the graphical desktop is missing because the colleague or student has attempted to remove the system Python, some of the system&#8217;s essential Python libraries and applications, or both. Other times, we see system applications, such as the Software Updater and the <code>ubuntu-drivers<\/code> driver selection tool, not working properly because the colleague or student has installed a different Python version alongside the system Python and then set the new Python version to be the default <code>python3<\/code> command system-wide.<\/p>\n\n\n\n<p>This damage often leaves the system unusable, preventing the colleague or student from working. The only solution is for NUIT to reinstall the Ubuntu operating system.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What to avoid<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Do not try to remove or replace the existing Python 3. Python is embedded into Ubuntu so heavily that an attempt to remove the python3 package will remove the Ubuntu desktop and hundreds of other packages, rendering the system unusable.<\/li>\n\n\n\n<li>Do not parallel install a second Python and make it answer to <code>python3<\/code> instead of the system Python. Redirecting the <code>python3<\/code> command to a Python other than the one you get from <code>apt install python3<\/code> <a href=\"https:\/\/www.mail-archive.com\/ubuntu-bugs@lists.ubuntu.com\/msg5933525.html\">will stop Ubuntu-specific applications and libraries from working<\/a>.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Solutions<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/pyenv\/pyenv\" data-type=\"URL\" data-id=\"https:\/\/github.com\/pyenv\/pyenv\">Pyenv<\/a> allows you to install multiple Python versions into your home directory without affecting the system Python, and switch between them easily.  Example: <code>pyenv install 3.8 ; pyenv local 3.8<\/code><\/li>\n\n\n\n<li><a href=\"https:\/\/pipx.pypa.io\/latest\/docs\/\">Pipx<\/a> will install applications written in Python and handle their dependencies elegantly. Limitations are that <a href=\"https:\/\/github.com\/pytorch\/pytorch\/issues\/60252#issuecomment-2326766951\" data-type=\"link\" data-id=\"https:\/\/github.com\/pytorch\/pytorch\/issues\/60252#issuecomment-2326766951\">optional modules that are not marked as dependencies aren&#8217;t installed and cannot trivially be added<\/a>. Example: <code>pipx install --include-deps ipykernel<\/code><\/li>\n\n\n\n<li><a href=\"https:\/\/pypi.org\/project\/pip\/\">Pip3<\/a> is needed to install Python libraries where there is no application component. You should use the <code>--user<\/code> flag with <code>pip3<\/code>.  Example: <code>pip3 install --user pysqlite3<\/code><\/li>\n\n\n\n<li><a href=\"https:\/\/virtualenv.pypa.io\/en\/latest\/\" data-type=\"URL\" data-id=\"https:\/\/virtualenv.pypa.io\/en\/latest\/\">Virtualenv<\/a> lets you install multiple versions of the same Python application or library to cope with different projects and switch between them.  Example: <code>virtualenv myenv ; source myenv\/bin\/activate<\/code>  <\/li>\n<\/ul>\n\n\n\n<p>Do not use <code>sudo<\/code> with any of these tools, they are all designed to be run with ordinary user privileges.<\/p>\n\n\n\n<p>Pyenv doesn&#8217;t switch Python versions within a Virtualenv instance, but you can mimic that feature as follows: <code>virtualenv --python ~\/.pyenv\/versions\/3.12.1\/bin\/python myenv<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"pyenvqs\">Quickstart for Pyenv<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Install dependencies<\/h4>\n\n\n\n<p>You, or your NUIT support staff, need to install some dependencies as root:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update; sudo apt install make build-essential libssl-dev zlib1g-dev \\\nlibbz2-dev libreadline-dev libsqlite3-dev curl git \\\nlibncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev \\\nlibzstd-dev<\/code><\/pre>\n\n\n\n<p>On Ubuntu 24.04 systems, you also need to install <code>zlib1g-dev<\/code> otherwise you get the unhelpfully-opaque:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>student@labC1QBRO:~$ pyenv install 3.12\nDownloading Python-3.12.5.tar.xz...\n-&gt; https:\/\/www.python.org\/ftp\/python\/3.12.5\/Python-3.12.5.tar.xz\nInstalling Python-3.12.5...\n\nBUILD FAILED (Ubuntu 24.04 using python-build 20180424)\n\nInspect or clean up the working tree at \/tmp\/python-build.20240903154016.7543\nResults logged to \/tmp\/python-build.20240903154016.7543.log\n\nLast 10 log lines:\n  File \"\/tmp\/python-build.20240903154016.7543\/Python-3.12.5\/Lib\/ensurepip\/__init__.py\", line 200, in _bootstrap\n    return _run_pip(&#091;*args, *_PACKAGE_NAMES], additional_paths)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"\/tmp\/python-build.20240903154016.7543\/Python-3.12.5\/Lib\/ensurepip\/__init__.py\", line 101, in _run_pip\n    return subprocess.run(cmd, check=True).returncode\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"\/tmp\/python-build.20240903154016.7543\/Python-3.12.5\/Lib\/subprocess.py\", line 571, in run\n    raise CalledProcessError(retcode, process.args,\nsubprocess.CalledProcessError: Command '&#091;'\/tmp\/python-build.20240903154016.7543\/Python-3.12.5\/python', '-W', 'ignore::DeprecationWarning', '-c', '\\nimport runpy\\nimport sys\\nsys.path = &#091;\\'\/tmp\/tmpjoslp4b2\/pip-24.2-py3-none-any.whl\\'] + sys.path\\nsys.argv&#091;1:] = &#091;\\'install\\', \\'--no-cache-dir\\', \\'--no-index\\', \\'--find-links\\', \\'\/tmp\/tmpjoslp4b2\\', \\'--root\\', \\'\/\\', \\'--upgrade\\', \\'pip\\']\\nrunpy.run_module(\"pip\", run_name=\"__main__\", alter_sys=True)\\n']' returned non-zero exit status 1.\nmake: *** &#091;Makefile:2027: install] Error 1<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Download and configure PyEnv<\/h4>\n\n\n\n<pre id=\"pyenvqscanneddeps\" class=\"wp-block-code\"><code>curl -fsSL https:\/\/pyenv.run | bash<\/code><\/pre>\n\n\n\n<p>Then <a href=\"https:\/\/github.com\/pyenv\/pyenv#b-set-up-your-shell-environment-for-pyenv\" data-type=\"link\" data-id=\"https:\/\/github.com\/pyenv\/pyenv#b-set-up-your-shell-environment-for-pyenv\">get the shell configuration for your shell<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Optional shell alias<\/h4>\n\n\n\n<p>Pyenv gives you a Python interpreter that answers to the name <code>python<\/code>.  To have it also answer to <code>python3<\/code>  and switch between the system Python and Pyenv-installed Pythons reliably, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install python-is-python3\n\nalias python3=python<\/code><\/pre>\n\n\n\n<p>Then add that alias to your shell&#8217;s run control file. The wide variety of shells in use means that we cannot give specific instructions for that.<\/p>\n\n\n\n<p>If you don&#8217;t install python-is-python3 and don&#8217;t set up the alias, you see outcomes like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~ $ pyenv local 3.12.1\n\n~ $ python --version\nPython 3.12.1\n\n~ $ python3 --version\nPython 3.10.12\n\n~ $ pyenv local system  \n\n~ $ python --version   \npyenv: python: command not found\n\nThe `python' command exists in these Python versions:\n  3.12.1<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"pyenvdemo\">Pyenv demonstration<\/h3>\n\n\n\n<p>The below demonstrates how Pyenv can be used to set up a directory for a project that needs a specific Python version without affecting the Python version used elsewhere:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~ $ pyenv global system\n\n~ $ python3 --version  \nPython 3.10.12\n\n~ $ python --version   \nPython 3.10.12\n\n~ $ mkdir pyenv-test ; cd pyenv-test\n\n~\/pyenv-test $ pyenv local 3.12.1             \n\n~\/pyenv-test $ python3 --version               \nPython 3.12.1\n\n~\/pyenv-test $ python --version               \nPython 3.12.1\n\n~\/pyenv-test $ cd ..\n\n~ $ python --version\nPython 3.10.12\n\n~ $ python3 --version\nPython 3.10.12<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>NUIT sometimes see University Ubuntu systems where the graphical desktop is missing because the colleague or student has attempted to remove the system Python, some of the system&#8217;s essential Python libraries and applications, or both. Other times, we see system applications, such as the Software Updater and the ubuntu-drivers driver selection tool, not working properly &hellip; <a href=\"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/2023\/12\/21\/safely-installing-python-applications-and-managing-additional-python-versions\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Safely installing Python applications and managing additional Python versions&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1447,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,6],"tags":[],"class_list":["post-228","post","type-post","status-publish","format-standard","hentry","category-python","category-ubuntu"],"_links":{"self":[{"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/posts\/228","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/users\/1447"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/comments?post=228"}],"version-history":[{"count":28,"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/posts\/228\/revisions"}],"predecessor-version":[{"id":303,"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/posts\/228\/revisions\/303"}],"wp:attachment":[{"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/media?parent=228"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/categories?post=228"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/helengriffiths\/wp-json\/wp\/v2\/tags?post=228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}