Skip to content

Instantly share code, notes, and snippets.

@dzogrim
Created January 2, 2025 13:23
Show Gist options
  • Save dzogrim/fd7f8962981bb3d3cf9aff56637685b8 to your computer and use it in GitHub Desktop.
Save dzogrim/fd7f8962981bb3d3cf9aff56637685b8 to your computer and use it in GitHub Desktop.
This script automates the detection and resolution of Python package architecture mismatches on macOS
#!/usr/bin/env bash
# This script automates the detection and resolution of Python package architecture mismatches on macOS.
#
# It scans for '.so' files compiled for x86_64 under all installed Python versions in '~/Library/Python',
# uninstalls the affected packages, and reinstalls them with ARM64 support. Additionally,
# it checks for dependency conflicts using pip check and resolves them by reinstalling problematic packages.
# This ensures compatibility with ARM-based systems, streamlining the transition from x86_64 to ARM architectures.
#
# TODO: clean-up everything and handle brew or port installations ...
set -o pipefail
echo "Starting Python package architecture check ..."
# Loop through all Python versions installed in "~/Library/Python"
for py_version in ~/Library/Python/3.*; do
PYTHON_BIN="$py_version/bin/python3"
PIP_BIN="$py_version/bin/pip3"
if [ -x "$PIP_BIN" ]; then
echo "Processing Python version: $py_version"
# Backup installed packages
$PIP_BIN list > /tmp/pip-packages-${py_version##*/}.txt
# Clear the pip cache
$PIP_BIN cache purge
# Upgrade pip now
sudo -H python3 -m pip install --upgrade pip --root-user-action=ignore
# Find x86_64 .so files and extract package names
find "$py_version/lib/python/site-packages/" -name "*.so" -exec file {} \; | \
grep -v "_brotli*" | \
grep -e "x86_64" | \
awk -F'site-packages/' '{print $2}' | \
cut -d'/' -f1 | \
sort -u > /tmp/x86-packages-${py_version##*/}.txt
# Uninstall x86_64 packages
if [ -s /tmp/x86-packages-${py_version##*/}.txt ]; then
echo "Uninstalling x86_64 packages for $py_version ..."
xargs $PIP_BIN uninstall -y < /tmp/x86-packages-${py_version##*/}.txt
else
echo "No x86_64 packages found for $py_version."
fi
# Reinstall packages as arm64
while read -r pkg; do
echo "Reinstalling $pkg for ARM64 ..."
ARCHFLAGS="-arch arm64" $PIP_BIN install --force-reinstall "$pkg"
done < /tmp/x86-packages-${py_version##*/}.txt
# Force some packages reinstallation
ARCHFLAGS="-arch arm64" $PIP_BIN install --force-reinstall \
PyYAML pyOpenSSL cryptography zope.hookable zope.interface brotli MarkupSafe mediapipe
ARCHFLAGS="-arch arm64" $PIP_BIN install zipp cffi --upgrade
# Check for dependency conflicts
$PIP_BIN check | awk '{print $1}' | sort -u > /tmp/pb_packages-${py_version##*/}.txt
if [ -s /tmp/pb_packages-${py_version##*/}.txt ]; then
echo "Fixing dependency conflicts for $py_version ..."
# Uninstall conflicting packages
xargs sudo $PIP_BIN uninstall --root-user-action=ignore -y < /tmp/pb_packages-${py_version##*/}.txt
# Reinstall them
while read -r pkg; do
ARCHFLAGS="-arch arm64" $PIP_BIN install --force-reinstall "$pkg"
done < /tmp/pb_packages-${py_version##*/}.txt
fi
# Clear the pip cache
$PIP_BIN cache purge
rm -rf ~/Library/Caches/pip
echo "Python version $py_version processed."
else
echo "No pip found for $py_version, skipping ..."
fi
done
echo "All Python versions processed successfully."
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment