migrating a python 3.9 virtual environment to python 3.10

I’m executing this on an M1 2020 MacBook Pro running macOS Monterey 12.4 and with Homebrew 3.4.11. This post shows how I migrated my Python 3.9 virtual environment’s site packages (the heart of a Python installation) to Python 3.10. The site packages are added to an environment whenever you perform a pip install ....

I do all my Python development completely within virtual environments. Python provides built-in tools to help you create and manage one or more virtual environments. A virtual environment is important as it provides a sandbox in which you, as the developer, can try anything you want to try, and won’t corrupt the base machine-wide Python environment. And if you reach the point where your Python virtual environment has gone sideways, it’s simple to create a new one to carry on. On this Mac I have one of my Python virtual environments at

When I want to create a virtual environment, for example for Python 3.10.4, I cd into the VPython folder and I run
/opt/homebrew/Cellar/python@3.10/3.10.4/bin/python3 -m venv 310

That creates a new subfolder into which all the virtual environment is located:

The reason for the long path to invoke Python 3.10.4 is because that’s where Homebrew installed it. I didn’t ask for that particular path, that’s just its default for the macOS environment.

I already have a virtual environment created for Python 3.9.12. With the new Python 3.10.4 virtual environment created I’m now ready to export my Python 3.9 site packages to Python 3.10 virtual environment. To start the process I need a list of what’s in the Python 3.9 virtual environment by activating the Python 3.9 virtual environment.

cd $HOME/Development/VPython
source 39/bin/activate
pip freeze > requirements.txt

You now have a complete list of all site packages in that virtual environment, complete with version numbers.

head requirements.txt

You can use requirements.txt to perform the import into the new Python virtual environment, except those version numbers can be a pain, especially if there are more up-to-date releases. I have encountered import failures in the past due to version restrictions due to explicit version requirements. I would strongly suggest that you remove those versions before using the requirements file.

cat requirements.txt | sed -e 's/=.*//' > requirements2.txt
head requirements2.txt

The sed (stream editor) command is using a simple regular expression to remove all text starting with the first equals symbol to the end of each line. I’m piping the results into another text file. Now you’re ready to import into the new Python virtual environment using the edited requirements.

I always open a second terminal to do the import so the original terminal remains in case something else needs to be done. So open a second terminal and in that terminal activate the Python 3.10 virtual environment. I’m going to assume in that new terminal you cd into your virtual Python top level folder as you did before.

cd $HOME/Development/VPython
source 310/bin/activate

Now import using requirements2.txt.

pip install -r ./requirements2.txt
lots of output as each package is installed...

During the mass install process you may see that some packages aren’t installed because of version collisions on other dependent packages that were installed earlier. When the mass import is finished, import each of those that errored out by hand, and the collisions will clean themselves up. Yes, it’s a pain, but then that’s the charm of any software system, its little quirks. The process I’ve outline will save lots of hours. I spent maybe 20 minutes doing all of these steps migrating hundreds of site packages.