Setting Up a Python 3.10 Virtual Environment with Pyenv and PyO3 on Macbook pro Silicon M1: A Step-by-Step Guide
In preparation for the PyData Amsterdam 2024 workshop on writing Python modules in Rust, I set up my development environment to ensure smooth sailing. If you’re interested in leveraging Rust’s performance for your Python projects, this guide will help you create an efficient, isolated development setup using pyenv, pyenv-virtualenv, and PyO3.
In this post, I’ll walk through setting up a Python 3.10 virtual environment on an M1 MacBook, perfect for projects integrating Rust with Python.
Why Use Pyenv, Pyenv-Virtualenv, and PyO3?
Before diving into the setup, let’s briefly discuss why these tools are valuable:
- Pyenv: Allows you to easily switch between multiple versions of Python. This is especially useful if you’re working on different projects that require different Python versions.
- Pyenv-Virtualenv: Helps isolate project dependencies. This ensures that system-level Python libraries don’t interfere with your project and vice versa.
- PyO3: A Rust library that allows you to write Python bindings in Rust, combining the performance and memory safety of Rust with Python’s ease of use. This is particularly useful for performance-critical projects.
Step-by-Step: Setting Up Your Virtual Environment
Step 1: Install Pyenv and Pyenv-Virtualenv
To get started, we need to install pyenv and pyenv-virtualenv. If you already have them installed, feel free to skip to the next step.
- Install pyenv and pyenv-virtualenv:
brew install pyenv pyenv-virtualenv
- Configure your shell to initialize pyenv and pyenv-virtualenv. For example, if you’re using zsh, add the following to your
~/.zshrc
file:
echo 'eval "$(pyenv init --path)"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zshrc
- After that, restart your terminal or run:
source ~/.zshrc
Step 2: Install Python 3.10
With pyenv set up, the next step is to install the specific Python version you want for your project. In this case, we’ll install Python 3.10.0.
- Install Python 3.10.0:
pyenv install 3.10.0
- Verify that Python 3.10.0 is installed:
pyenv versions
You should see Python 3.10.0 listed in the output.
Step 3: Create a Virtual Environment
Now, let’s create a virtual environment specifically for this project using pyenv-virtualenv.
- Create a virtual environment named
pyo3
:
pyenv virtualenv 3.10.0 pyo3
This creates a virtual environment based on Python 3.10.0, which will allow us to manage dependencies specific to our project.
Step 4: Activate the Virtual Environment
To start working in your virtual environment, you’ll need to activate it:
- Activate the
pyo3
environment: - Verify the Python version:
You should see Python 3.10.0
, confirming that your environment is using the correct Python version.
Step 5: Install PyO3 and Rust
Since we plan to use PyO3 for Rust and Python integration, let’s install maturin, a tool that helps build Python packages written in Rust.
- Install maturin:
pip install maturin
- Set up Rust by installing it via rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
At this point, you have a fully functioning Python virtual environment using Python 3.10 and are ready to build Python modules in Rust with PyO3.
Benefits of Pyenv, Pyenv-Virtualenv, and PyO3
- Isolated Environments: Using pyenv and pyenv-virtualenv allows you to isolate dependencies per project, preventing version conflicts. This is crucial when working on projects that require specific Python versions or dependency versions.
- Easy Python Version Management: Pyenv makes it easy to switch between multiple Python versions on the same machine. This is especially useful when working on projects that require different Python versions, ensuring that you can always match the specific Python version for each project.
- Cross-Language Flexibility with PyO3: PyO3 bridges the gap between Python and Rust, allowing you to take advantage of Rust’s memory safety, concurrency, and performance benefits while maintaining the flexibility of Python. This is particularly useful for performance-critical Python applications, where you want to speed up certain components without rewriting the entire application.
- Efficiency with Rust: By using maturin with PyO3, you can build and distribute Python packages that use Rust behind the scenes, combining Python’s simplicity with Rust’s high performance and safety guarantees.
Conclusion
Setting up an environment using pyenv, pyenv-virtualenv, and PyO3 creates a highly efficient development setup for building Python projects powered by Rust. Whether you’re switching between Python versions for various projects or improving performance in your Python applications by leveraging Rust, this setup ensures your environment is isolated, manageable, and optimized for development.