PyChoose: Switch between installed versions of Python

You can switch between different installed versions of Python by simply prepending to your PATH. However, this goes wrong in some scenarios, such as when a tool like ‘virtualenv’ is installed in one Python version, but not in another. Pretty soon you will be executing your project with one Python version, but referencing the site-packages of another. When switching, other versions of Python need to be stripped from your PATH.

As a solution, I present a new Python module, pychoose. For the moment this is Windows only:

>python -V
Python 2.6.4
>easy_install pychoose
>pychoose 24
(Py24) >python -V
Python 2.4.4
(Py24) >exit
>python -V
Python 2.6.4

It prepends to the PATH as above, but it also filters other Python versions out the PATH. It modifies the PROMPT to show the user they are operating in a modified environment. It works by spawning a new shell with the modified environment. To return to your default Python interpreter, type ‘exit’.

PyPI page:

Subversion repository:

Preview the module source code.

It seems to work for simple scenarios, but there are a bunch of known problems with it (see the PyPI page above), which I’d like to fix if people think this is useful. I just whipped this up and don’t really understand the issues surrounding this. In particular is spawning a new shell the best way to modify the current console’s environment? Is a less-instrusive alternative to generate .bat file which can be executed to change the current shell’s environment?

Feedback & suggestions very welcome.

16 thoughts on “PyChoose: Switch between installed versions of Python

  1. Ahar, yes, setx doesn’t actually set the environment variable in the current process – it just changes the registry for new processes.

    Thanks heaps for all of that Edwin, I’ll have to go experiment with PYTHON_HOME, that might be a much smarter solution…

  2. This kind of batch script works in admin mode of command line:

    IF “%1” == “3.1” SETX PYTHON_HOME “C:\Program Files (x86)\Python31” -m
    IF “%1” == “2.7” SETX PYTHON_HOME “C:\Program Files (x86)\Python27” -m

    However, unlike I thought, I still need to open a new command window to get the new Python version.

  3. oops okay, so doing SETX to PYTHON_HOME with -m works, but then it is still necessary to open a new command window, unlike I had thought.

  4. Instead of mingling with the path directly, isn’t it easier to mingle with a PYTHON_HOME environment variable?

    A simple batch script could set PYTHON_HOME in the shell you have open. Then in path refer to %PYTHON_HOME%.

  5. Hey srid, thanks for that.

    Having a ‘python26.exe’ link is brilliant – we discuss that idea further up in the comments.

    The problem with that though, is that it can only work when I’m invoking python manually from the command line. I cannot build a program which invokes python like that, because of course I cannot expect that python26 will exist on anyone else’s system.

    Best regards.

  6. This is not necessary for ActivePython [] which installs a “python26.exe” along with “python.exe”.

  7. Hey masklinn and ot,

    Thanks a lot – I will check out both BPT and python_select.

    And Ted – thanks for the encouragement!

  8. Hey Chris Arndt,
    Thanks for that! I think the technique of having ‘pythonX.X’ executables around for each installed version is a good one, and I add my own versions of this even on Windows. (if you add ‘.lnk’ and ‘.exe.lnk’ to your PATHEXT variable, then you can make shortcuts to the different python versions, which are executable from the command-line)

    The problem though, which pychoose is designed to overcome, is when you have some third party tool or component which invokes python in a new process, simply as ‘python’ – I want to be able to control which version of Python it will end up getting.

    This is even true for my own components – I might want to distribute a tool which invokes ‘python’. I cannot make it invoke ‘python2.5’, because on Windows I cannot count on such a shortcut existing on other people’s systems. Nevertheless, during development, I want to control which version of Python it invokes.

    Best regards,

  9. Hey Gustavo Narea,
    Thanks for the comment. The problem with virtualenvwrapper is that it requires me to use virtualenv. The problem with using virtualenv on projects where it isn’t required is that I quickly end up with many virtual environments per project – one per OS that I work on the project on, and also, for Windows, one per machine that I work on the project from (since I can’t get –relocatable to work for me, at least not on Windows) Keeping them all in sync and up-to-date starts to become a chore, and wastes hundreds of megabytes of storage for *each* project, no matter how large or small.

    The idea of pychoose is that it would work without having to do any of that, regardless of whether using virtualenv at all.

    Have I misunderstood at any step along the way?

  10. It doesn’t yet work with Python 3.0, nor with versions prior to the introduction of subprocess to the standard library. I fixed some of these issues earlier this evening, but on another PC – they will be checked in and/or updated on PyPI tomorrow.

  11. On UNIX environments BPT ( can be used for the same purpose: just install different python versions into different boxes. It also provides a fork of PIP to automatically install python packages from pypi inside the box.

  12. I don’t think this is even needed on non-Windows systems. There, the Python binary is usually not only installed as “python”, but also as “pythonX.Y” (the default version is often just a hardlink). You can switch between Python versions on demand.

    The same goes for easy_install (i.e. you have easy_install, easy_install-2.5, easy_install-2.6, etc.) and I usually do the same with virtualenv:

    sudo easy_install-2.4 virtualenv
    sudo cp /usr/bin/virtualenv /usr/bin/virtualenv-2.4
    sudo easy_install-2.5 virtualenv
    sudo cp /usr/bin/virtualenv /usr/bin/virtualenv-2.5
    sudo easy_install-2.6 virtualenv
    sudo cp /usr/bin/virtualenv /usr/bin/virtualenv-2.6

    which leaves “virtualenv” as the default version using Python 2.6.

  13. Awesome idea. Can’t wait to see it develop and make it over to *nix eventually!

Leave a Reply