Python Sürüm Uyumsuzluk Sorunlarını Giderme
Prodüksiyonda bir Python uygulaması çalıştırıyorsunuz, her şey güzel görünüyor. Sabah işe geliyorsunuz, uygulama çökmüş. Log’lara bakıyorsunuz: ModuleNotFoundError, SyntaxError, ya da daha kötüsü hiçbir anlam ifade etmeyen bir ImportError. Nedeni? Birisi sunucuya Python güncellemesi yapmış ya da sistem paketi yöneticisi Python bağımlılıklarını güncellemiş. Tanıdık geliyor mu? Python sürüm uyumsuzlukları, sysadmin ve geliştirici hayatının en sinir bozucu sorunlarından biridir. Bu yazıda bu sorunları kökten çözmenin yollarını konuşacağız.
Python Sürüm Uyumsuzluğu Neden Olur?
Python’un birden fazla sürümünün aynı sistemde bulunması, aslında son derece yaygın bir durum. Linux dağıtımlarının büyük çoğunluğu sistem araçları için Python kullanır ve bu Python genellikle /usr/bin/python ya da /usr/bin/python3 yolundadır. Siz kendi uygulamanız için farklı bir sürüm kurduğunuzda işler karışmaya başlar.
Temel sorun kaynakları şunlardır:
- Sistem Python’u ile uygulama Python’unun çakışması: Ubuntu 22.04 Python 3.10 ile gelir, siz Python 3.11 kullanıyorsunuzdur.
- pip ile kurulan paketlerin yanlış Python’a gitmesi:
pip installdediğinizde hangi Python’un pip’i çalışıyor? - Sanal ortam sorunları: Virtualenv silinmiş ya da Python yorumlayıcısı taşınmış olabilir.
- shebang satırı hataları: Script’in üstündeki
#!/usr/bin/pythonsatırı yanlış sürüme işaret edebilir. - PATH karmaşası: Birden fazla Python kurulumu PATH’te farklı önceliklerle sıralanmış olabilir.
Mevcut Durumu Tespit Etmek
Sorun gidermede ilk adım her zaman mevcut durumu anlamaktır. Sistemdeki tüm Python kurulumlarını bulalım.
# Sistemdeki tüm Python binary'lerini bul
which -a python python3 python3.10 python3.11 python3.12 2>/dev/null
# Daha kapsamlı arama
find /usr /opt /home -name "python*" -type f 2>/dev/null | grep -E "python[0-9.]?$" | sort
# Her birinin sürümünü kontrol et
for py in $(find /usr /opt -name "python*" -type f 2>/dev/null | grep -E "python[0-9.]+$"); do
echo "$py: $($py --version 2>&1)"
done
Bu komutlar çıktısına bakarak sistemde kaç tane Python olduğunu ve hangisinin ne sürüm olduğunu görebilirsiniz. Şimdi hangi pip‘in nereye paket kurduğunu da anlayalım:
# pip'in hangi Python'u kullandığını öğren
pip --version
pip3 --version
# Python içinden de kontrol edebilirsiniz
python3 -c "import sys; print(sys.executable)"
python3 -c "import sys; print(sys.path)"
# Kurulu paketlerin nereye gittiğini gör
python3 -c "import site; print(site.getsitepackages())"
Bu noktada sisteminizin tam resmini görmeye başlarsınız. Eğer pip --version çıktısında python 3.8 görüyorsanız ama siz python3 --version ile 3.11 diyorsa, paketleriniz yanlış sürüme kuruluyordur.
update-alternatives ile Python Yönetimi (Linux)
Linux sistemlerde birden fazla Python sürümü varsa update-alternatives aracı çok işe yarar. Bu araç, hangi python3 komutunun hangi binary’ye işaret edeceğini merkezi olarak yönetmenizi sağlar.
# Mevcut Python alternativelerini listele
update-alternatives --list python3
# Python 3.10 ve 3.11'i alternatif olarak ekle
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 2
# İnteraktif seçim menüsü
sudo update-alternatives --config python3
# Direkt olarak belirli bir sürümü seç (öncelik numarasına göre)
sudo update-alternatives --set python3 /usr/bin/python3.11
Dikkat: Sistem araçları eski Python sürümlerine bağımlı olabilir. update-alternatives ile sistem Python’unu değiştirirken dikkatli olun. apt, yum gibi paket yöneticileri sistem Python’una bağlı çalışır.
pyenv ile Sürüm Yönetimi
Prodüksiyonda birden fazla Python sürümü yönetmenin en temiz yolu pyenv kullanmaktır. Pyenv, sistem Python’una hiç dokunmadan istediğiniz kadar Python sürümü kurmanızı sağlar.
# pyenv kurulumu (Linux/macOS)
curl https://pyenv.run | bash
# .bashrc veya .zshrc'ye ekle
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
# Shell'i yeniden yükle
source ~/.bashrc
# Kurulabilir Python sürümlerini listele
pyenv install --list | grep -E "^s+3.(10|11|12)"
# Belirli bir sürümü kur
pyenv install 3.11.8
pyenv install 3.10.14
# Global Python sürümünü ayarla
pyenv global 3.11.8
# Sadece belirli bir proje dizini için sürüm ayarla
cd /opt/myapp
pyenv local 3.10.14
# Mevcut aktif sürümü kontrol et
pyenv version
pyenv versions
pyenv local komutu çalıştırıldığında dizinde .python-version adında bir dosya oluşturur. Bu dosya sayesinde o dizine her girdiğinizde pyenv otomatik olarak doğru Python sürümünü aktive eder. CI/CD pipeline’larınız bu dosyayı okuyarak doğru sürümü kullanabilir.
Sanal Ortam Sorunlarını Gidermek
Sanal ortam (virtualenv/venv) sorunları uyumsuzluk problemlerinin büyük bölümünü oluşturur. Bir sanal ortam oluşturulduğunda, Python yorumlayıcısına sembolik link ya da hard link içerir. Eğer orijinal Python kaldırılırsa veya güncelleme ile değişirse sanal ortam bozulur.
# Sanal ortamın hangi Python'u kullandığını kontrol et
ls -la /opt/myapp/venv/bin/python*
# Sanal ortamdaki Python binary'sinin geçerli olup olmadığını test et
/opt/myapp/venv/bin/python --version 2>&1 || echo "BOZUK SANAL ORTAM"
# Sanal ortamın orijinal Python'unu öğren
cat /opt/myapp/venv/pyvenv.cfg
# Tipik pyvenv.cfg içeriği şu şekilde görünür:
# home = /usr/bin
# implementation = CPython
# version_info = 3.11.8
# virtualenv = 20.24.5
# include-system-site-packages = false
# base-prefix = /usr
# base-exec-prefix = /usr
# base-executable = /usr/bin/python3.11
Sanal ortam bozulmuşsa en temiz çözüm onu yeniden oluşturmaktır:
# Mevcut gereksinimleri yedekle
/opt/myapp/venv/bin/pip freeze > /tmp/requirements_backup.txt
# Eski sanal ortamı sil
rm -rf /opt/myapp/venv
# Doğru Python ile yeni sanal ortam oluştur
python3.11 -m venv /opt/myapp/venv
# Paketleri geri yükle
/opt/myapp/venv/bin/pip install -r /tmp/requirements_backup.txt
# Test et
/opt/myapp/venv/bin/python -c "import your_module; print('Tamam')"
Gerçek Dünya Senaryosu: Django Uygulaması Çöküyor
Diyelim ki Ubuntu 20.04 üzerinde Python 3.8 ile çalışan bir Django uygulamanız var. Sistem yöneticisi Ubuntu 22.04’e yükseltme yaptı ve Python 3.10 geldi. Uygulama çöktü. Ne yaparsınız?
# Önce durumu anlayalım
python3 --version # 3.10.x görürsünüz
cat /opt/django_app/venv/pyvenv.cfg # base-executable: /usr/bin/python3.8
# Uygulama log'larına bakın
journalctl -u django_app.service -n 50
# Python 3.8 hala var mı?
which python3.8
/usr/bin/python3.8 --version # Muhtemelen "No such file" hatası alırsınız
# Çözüm adımları:
# 1. Python 3.8'i deadsnakes PPA'dan kur (Ubuntu için)
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.8 python3.8-venv python3.8-dev
# 2. Sanal ortamı yeniden oluştur
cd /opt/django_app
pip freeze > requirements_backup.txt # Bu çalışmıyorsa
# cat venv/lib/python3.8/site-packages/... manuel kontrol
python3.8 -m venv venv_new
venv_new/bin/pip install -r requirements.txt
# 3. Sembolik linki güncelle veya servisi yönlendir
mv venv venv_old
mv venv_new venv
# 4. Servisi yeniden başlat
sudo systemctl restart django_app
# 5. Çalıştığını doğrula
sudo systemctl status django_app
Paket Uyumsuzluklarını Tespit Etmek
Bazen Python sürümü doğru olmasına rağmen paketler uyumsuz olabilir. Bu durumu tespit etmek için:
# Tüm paketlerin uyumluluğunu kontrol et
pip check
# Belirli bir paketin neye ihtiyaç duyduğunu gör
pip show numpy | grep -E "Requires|Required-by"
# Çakışan paketleri bul
pip list --outdated
# Paket bağımlılık ağacını görselleştir (pipdeptree kur)
pip install pipdeptree
pipdeptree --warn conflict
# Sadece çakışanları göster
pipdeptree --warn conflict 2>&1 | grep -E "Warning|conflict"
pip check komutu kurulu paketler arasındaki uyumsuzlukları raporlar. Örnek çıktı:
# pip check örnek çıktısı
requests 2.28.0 requires urllib3<1.27,>=1.21.1, but you have urllib3 2.0.4 which is incompatible.
boto3 1.26.0 requires botocore<1.30.0,>=1.29.0, but you have botocore 1.30.1 which is incompatible.
Bu tür uyumsuzluklarda yapılacak şey bağımlılıkları doğru versiyonlara sabitlemektir.
requirements.txt ve Sürüm Sabitleme
Birçok sorunun kökü gevşek yazılmış requirements dosyalarıdır. requests yazmak yerine requests==2.28.0 yazmak gerekir.
# Mevcut ortamı tam olarak sabitle (production snapshot)
pip freeze > requirements.txt
# requirements.txt içinde şu gibi girişler olmalı:
# requests==2.28.2
# Django==4.2.3
# numpy==1.24.3
# Bağımlılıkları kontrol ederek kur
pip install -r requirements.txt --dry-run
# Hash doğrulaması ile daha güvenli kurulum
pip hash requests-2.28.2-py3-none-any.whl
pip install -r requirements.txt --require-hashes
# pip-compile ile bağımlılıkları otomatik sabitle (pip-tools paketi)
pip install pip-tools
pip-compile requirements.in # requirements.in: sadece direkt bağımlılıklar
# Çıktı: requirements.txt - tüm alt bağımlılıklar sabitlenmiş halde
Docker ile Sürüm Uyumsuzluğunu Kökten Çözmek
En kalıcı çözüm uygulamayı container içine almaktır. Docker sayesinde Python sürümü uyumsuzluğu neredeyse imkansız hale gelir.
# Örnek Dockerfile
cat > Dockerfile << 'EOF'
FROM python:3.11.8-slim-bookworm
WORKDIR /app
# Önce requirements'ı kopyala (layer cache optimizasyonu)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Sonra uygulama kodunu kopyala
COPY . .
# Python sürümünü build sırasında doğrula
RUN python --version && pip check
CMD ["python", "app.py"]
EOF
# Image oluştur
docker build -t myapp:3.11.8 .
# Çalıştır
docker run --rm myapp:3.11.8
# Birden fazla Python sürümünde test et
for pyver in 3.10 3.11 3.12; do
echo "=== Python $pyver ile test ==="
docker run --rm python:${pyver}-slim pip install -r requirements.txt && echo "OK"
done
Shebang Satırı Sorunları
Script’lerin doğru Python ile çalışmasını sağlamak için shebang satırını doğru yazmak kritiktir:
# YANLIS - mutlak path kullanmak taşınabilir değil
#!/usr/bin/python3
# DOGRU - env ile PATH'teki ilk Python'u kullan
#!/usr/bin/env python3
# Belirli sürüm gerektiriyorsa
#!/usr/bin/env python3.11
# Sanal ortam script'leri için (sanal ortam aktifken)
# Sanal ortamın python'unu direkt kullan
/opt/myapp/venv/bin/python myscript.py
# Script içinden Python sürümünü doğrula
python3 -c "
import sys
if sys.version_info < (3, 10):
print(f'HATA: Python 3.10+ gerekli, mevcut: {sys.version}')
sys.exit(1)
print(f'Python sürümü uygun: {sys.version}')
"
Cron Job ve Systemd Servislerinde Sürüm Sorunları
Cron job’larda en yaygın sorun, kullanıcının PATH’inin cron ortamında bulunmamasıdır:
# YANLIS cron girişi - hangi Python?
* * * * * python3 /opt/scripts/backup.py
# DOGRU - tam path kullan
* * * * * /opt/myapp/venv/bin/python /opt/scripts/backup.py
# Ya da sanal ortamı aktive et
* * * * * source /opt/myapp/venv/bin/activate && python /opt/scripts/backup.py
# Systemd servis dosyasında da tam path kullan
cat /etc/systemd/system/myapp.service
# [Service]
# ExecStart=/opt/myapp/venv/bin/python /opt/myapp/app.py
# Environment=PYTHONPATH=/opt/myapp
# Systemd ile Python sürümünü logla
sudo systemctl start myapp
sudo journalctl -u myapp -f
Hata Mesajlarını Okumak ve Çözmek
Yaygın hata mesajlarını ve çözümlerini hızlıca gözden geçirelim:
ModuleNotFoundError: No module named 'xyz' hatası için:
- Modülün sanal ortama kurulu olup olmadığını kontrol edin:
pip list | grep xyz - Doğru Python’u kullandığınızdan emin olun:
which python3 - Sanal ortamın aktif olup olmadığını kontrol edin:
echo $VIRTUAL_ENV
SyntaxError: invalid syntax hatası Python sürüm uyumsuzluğunun klasik belirtisidir. Python 3.10+ ile gelen match/case ifadesi eski sürümlerde bu hatayı verir. Sürümü kontrol edin ve doğru yorumlayıcıyı kullanın.
ImportError: cannot import name 'X' from 'Y' hatası için paketin doğru sürümünü kontrol edin: pip show paketadi. Genellikle paketin farklı sürümünde API değişimi olmuştur.
Sonuç
Python sürüm uyumsuzluğu sorunları karmaşık görünse de sistematik bir yaklaşımla çözülebilir. Önce mevcut durumu tespit edin, hangi Python’un nerede olduğunu ve pip’in nereye paket kurduğunu bilin. Ardından her proje için izole sanal ortamlar kullanın ve requirements.txt’i sürüm numaralarıyla sabitleyin.
Uzun vadeli çözüm için pyenv gibi bir sürüm yöneticisi benimseyin. Sistem Python’una hiç dokunmayın. Prodüksiyon ortamlarında ise Docker kullanmak sizi bu tür sorunların büyük bölümünden tamamen kurtarır. Cron job’larda ve systemd servislerinde her zaman tam path kullanın, PATH ortam değişkenine güvenmeyin.
Bu yazıda anlattığım adımları takip ederek hem mevcut uyumsuzluk sorunlarınızı giderebilir hem de gelecekte benzer sorunların önüne geçebilirsiniz. Python ekosistemi hızlı değişiyor, ama doğru altyapıyı kurarsanız bu değişimler sizi etkilemez.
