Python Raspberry Pi on Bookworm works differently from previous OS versions. Python 3.11 is pre-installed and ready to use, but Bookworm enforces a system-managed Python environment that blocks pip install commands run outside a virtual environment. This protects the OS from package conflicts but surprises users who followed older guides. This article covers running scripts, creating virtual environments, installing packages correctly, accessing GPIO hardware with gpiozero, and the tools that make Python development practical on Pi.
Last tested: Raspberry Pi OS Bookworm Lite 64-bit | May 3, 2026 | Raspberry Pi 4 Model B | Python 3.11.2 | pip 23.0
Key Takeaways
- On Bookworm,
pip install packagenamefails with “externally-managed-environment” because the OS protects its Python packages from user-installed libraries. The correct fix for a project is to use a virtual environment (python3 -m venv). The quick fix for a one-off script ispip install packagename --break-system-packages. Do not usesudo pip install. - Python 2 is not installed on Bookworm. Only Python 3 is present. The command
python(without the 3) is not available by default. Usepython3for all commands and scripts. - For GPIO hardware access on Bookworm, use
gpiozerorather thanRPi.GPIO. The gpiozero library ships with Raspberry Pi OS, requires no additional install, and works correctly on Pi 4 and Pi 5. RPi.GPIO requires kernel patches that are not present in the Pi 5 kernel.
Python Raspberry Pi: What Is Installed on Bookworm
Raspberry Pi OS Bookworm ships with Python 3.11 installed and available system-wide. There is no separate installation step required. Confirm the version and location:
python3 --version
# Python 3.11.2
which python3
# /usr/bin/python3
pip3 --version
# pip 23.0 from /usr/lib/python3/dist-packages/pip (python 3.11)
Python 3.11 is the system Python. It is used by OS tools and Raspberry Pi OS packages. Bookworm prevents user-installed pip packages from interfering with these system packages by marking the environment as “externally managed.” This is the PEP 668 change and it affects every Debian 12-based system, not just Raspberry Pi OS.
Running Python Scripts
Create and run a script from the terminal:
nano hello.py
Write your script:
print("Hello from Raspberry Pi")
import sys
print(f"Python {sys.version}")
print(f"Running on: {sys.platform}")
Save with Ctrl+O, exit with Ctrl+X, then run:
python3 hello.py
Expected result: The script prints the message, Python version string, and linux as the platform. If you see a ModuleNotFoundError, the required package is not installed. The next section covers installation.
To make a script executable and run it directly without typing python3 each time, add a shebang line and set the execute bit:
# Add as the first line of your script:
#!/usr/bin/env python3
# Set executable:
chmod +x hello.py
# Run directly:
./hello.py
Virtual Environments: The Correct Package Approach on Bookworm
A virtual environment is an isolated Python installation for a specific project. Packages installed inside a virtual environment do not affect the system Python and do not trigger the externally-managed-environment error. This is the right approach for any project with more than one or two dependencies.
# Create a virtual environment named 'venv' in the current directory
python3 -m venv venv
# Activate it
source venv/bin/activate
# Your prompt now shows (venv)
# Install packages freely within the venv
pip install requests
# Run your script
python3 myscript.py
# Deactivate when done
deactivate
Expected result: After activation, which python3 shows a path inside the venv directory rather than /usr/bin/python3. pip install commands succeed without any warnings or errors.
For a script that runs as a systemd service (always-on sensor logger, MQTT publisher, etc.), embed the virtual environment path in the ExecStart line rather than activating it:
[Service]
ExecStart=/home/pi/myproject/venv/bin/python3 /home/pi/myproject/script.py
This uses the virtual environment Python and its installed packages without needing to activate the venv first. See Grafana InfluxDB Raspberry Pi for a real-world example using influxdb-client in a sensor logging script with this pattern.
Quick fix for one-off scripts
If you need a single package for a quick test and do not want to create a virtual environment, use:
pip install requests --break-system-packages
This installs into the user site-packages at ~/.local/lib/python3.11/site-packages/. It is safe for single-user Pi setups but accumulates packages over time. Use virtual environments for anything you plan to keep running.

GPIO Hardware Access with gpiozero
The gpiozero library is the current standard for GPIO access on Pi 4 and Pi 5. It ships with Raspberry Pi OS and requires no installation. The older RPi.GPIO library requires kernel patches not present in the Pi 5 kernel and should not be used for new projects.
A basic LED blink script using gpiozero:
from gpiozero import LED
from time import sleep
led = LED(17) # GPIO pin 17
while True:
led.on()
sleep(1)
led.off()
sleep(1)
A button input example:
from gpiozero import Button, LED
button = Button(2) # GPIO pin 2
led = LED(17) # GPIO pin 17
button.when_pressed = led.on
button.when_released = led.off
# Keep the script running
input("Press Enter to quit
")
gpiozero uses a higher-level API than RPi.GPIO. Instead of setting pin modes and writing high/low values manually, you work with LED, Button, DistanceSensor, MotionSensor, and other component classes. The library handles the underlying pin state management.
For GPIO projects that use the HC-SR04 ultrasonic sensor, DHT22 temperature sensor, or similar hardware, see Raspberry Pi Robot Basics for worked gpiozero examples with real hardware.
Useful Tools and Practices
Thonny IDE
Thonny is a beginner-friendly Python IDE that ships with Raspberry Pi OS Desktop. It provides a file editor, run button, output pane, and a variable inspector that shows the current value of all variables while a script runs. It is not installed on Raspberry Pi OS Lite. Install it with:
sudo apt install thonny -y
For headless Pi setups where you SSH in from another machine, VS Code with the Remote SSH extension is more practical than Thonny. It gives you a full editor running on the Pi from your laptop interface.
Checking installed packages
# List packages in the active environment (venv or system)
pip list
# Check if a specific package is installed
pip show requests
# Check what is installed in the system Python (not venv)
pip3 list
Running a script at boot
For a Python script that should run automatically when the Pi starts, create a systemd service unit:
sudo nano /etc/systemd/system/myscript.service
[Unit]
Description=My Python Script
After=network.target
[Service]
User=pi
ExecStart=/home/pi/myproject/venv/bin/python3 /home/pi/myproject/script.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now myscript.service
sudo systemctl status myscript.service
Expected result: The service shows active (running) status. Logs are accessible with journalctl -u myscript.service -f.
FAQ
Why does pip install fail on Bookworm?
Bookworm enforces PEP 668, which prevents pip from installing packages into the system Python environment. The error “externally-managed-environment” is intentional. The correct fix is to create a virtual environment with python3 -m venv venv and activate it before installing. For a one-off package, pip install packagename --break-system-packages installs into the user site-packages without touching the system Python.
Should I use Python 2 or Python 3?
Python 3 only. Python 2 reached end of life in January 2020 and is not installed on Bookworm. All current libraries, frameworks, and examples target Python 3. If you encounter an old guide or script written for Python 2, it requires updating before it will run on a current Pi.
How do I install a newer Python version than what Bookworm provides?
Use pyenv to manage multiple Python versions alongside the system Python. pyenv builds Python from source and installs it in your home directory without affecting the OS Python. Install pyenv, run pyenv install 3.12.x, then pyenv local 3.12.x in your project directory to use that version for that project only. This is the correct approach for targeting a specific Python version without breaking OS tools.
Can Python access the Pi’s GPIO pins?
Yes. Use the gpiozero library which is pre-installed on Raspberry Pi OS. It provides high-level component classes for LEDs, buttons, sensors, and motors. The older RPi.GPIO library works on Pi 4 but has known issues on Pi 5 due to kernel differences. For new projects on either Pi model, use gpiozero.
How do I read sensor data from Python?
Depends on the sensor interface. I2C sensors (BME280, INA219) use the smbus2 library and the I2C bus at /dev/i2c-1. SPI sensors use spidev. One-wire sensors (DS18B20 temperature) read from /sys/bus/w1/devices/. GPIO-connected sensors (DHT22, HC-SR04) use gpiozero or dedicated libraries like adafruit-circuitpython-dht. Enable the relevant interface in raspi-config under Interface Options before connecting the sensor. See Raspberry Pi Companion Boards: Pico W and MQTT for sensor integration examples.
References
- https://www.python.org/downloads/
- https://gpiozero.readthedocs.io/
- https://peps.python.org/pep-0668/
- https://github.com/pyenv/pyenv
About the Author
Chuck Wilson has been programming and building with computers since the Tandy 1000 era. His professional background includes CAD drafting, manufacturing line programming, and custom computer design. He runs PidiyLab in retirement, documenting Raspberry Pi and homelab projects that he actually deploys and maintains on real hardware. Every article on this site reflects hands-on testing on specific hardware and OS versions, not theoretical walkthroughs.
Last tested hardware: Raspberry Pi 4 Model B. Last tested OS: Raspberry Pi OS Bookworm Lite 64-bit. Python 3.11.2.

