# Virtual Environments { #virtual-environments }
Python projeleriyle çalışırken, her proje için kurduğunuz package'leri birbirinden izole etmek adına büyük ihtimalle bir **virtual environment** (veya benzer bir mekanizma) kullanmalısınız.
/// info | Bilgi
Virtual environment'leri, nasıl oluşturulduklarını ve nasıl kullanıldıklarını zaten biliyorsanız bu bölümü atlamak isteyebilirsiniz. 🤓
///
/// tip | İpucu
**Virtual environment**, **environment variable** ile aynı şey değildir.
**Environment variable**, sistemde bulunan ve programların kullanabildiği bir değişkendir.
**Virtual environment** ise içinde bazı dosyalar bulunan bir klasördür.
///
/// info | Bilgi
Bu sayfada **virtual environment**'leri nasıl kullanacağınızı ve nasıl çalıştıklarını öğreneceksiniz.
Eğer Python'ı kurmak dahil her şeyi sizin yerinize yöneten bir **tool** kullanmaya hazırsanız, uv'yi deneyin.
///
## Proje Oluşturun { #create-a-project }
Önce projeniz için bir klasör oluşturun.
Ben genelde home/user klasörümün içinde `code` adlı bir klasör oluştururum.
Sonra bunun içinde her proje için ayrı bir klasör oluştururum.
```console
// Go to the home directory
$ cd
// Create a directory for all your code projects
$ mkdir code
// Enter into that code directory
$ cd code
// Create a directory for this project
$ mkdir awesome-project
// Enter into that project directory
$ cd awesome-project
```
## Virtual Environment Oluşturun { #create-a-virtual-environment }
Bir Python projesi üzerinde **ilk kez** çalışmaya başladığınızda, projenizin içinde **virtual environment** oluşturun.
/// tip | İpucu
Bunu her çalıştığınızda değil, **proje başına sadece bir kez** yapmanız yeterlidir.
///
//// tab | `venv`
Bir virtual environment oluşturmak için, Python ile birlikte gelen `venv` modülünü kullanabilirsiniz.
```console
$ python -m venv .venv
```
/// details | Bu komut ne anlama geliyor
* `python`: `python` adlı programı kullan
* `-m`: bir modülü script gibi çalıştır; bir sonraki kısımda hangi modül olduğunu söyleyeceğiz
* `venv`: normalde Python ile birlikte kurulu gelen `venv` modülünü kullan
* `.venv`: virtual environment'i yeni `.venv` klasörünün içine oluştur
///
////
//// tab | `uv`
Eğer `uv` kuruluysa, onunla da virtual environment oluşturabilirsiniz.
```console
$ uv venv
```
/// tip | İpucu
Varsayılan olarak `uv`, `.venv` adlı bir klasörde virtual environment oluşturur.
Ancak ek bir argümanla klasör adını vererek bunu özelleştirebilirsiniz.
///
////
Bu komut `.venv` adlı bir klasörün içinde yeni bir virtual environment oluşturur.
/// details | `.venv` veya başka bir ad
Virtual environment'i başka bir klasörde de oluşturabilirsiniz; ancak buna `.venv` demek yaygın bir konvansiyondur.
///
## Virtual Environment'i Aktif Edin { #activate-the-virtual-environment }
Oluşturduğunuz virtual environment'i aktif edin; böylece çalıştırdığınız her Python komutu veya kurduğunuz her package onu kullanır.
/// tip | İpucu
Projede çalışmak için **yeni bir terminal oturumu** başlattığınız **her seferinde** bunu yapın.
///
//// tab | Linux, macOS
```console
$ source .venv/bin/activate
```
////
//// tab | Windows PowerShell
```console
$ .venv\Scripts\Activate.ps1
```
////
//// tab | Windows Bash
Ya da Windows'ta Bash kullanıyorsanız (örn. Git Bash):
```console
$ source .venv/Scripts/activate
```
////
/// tip | İpucu
Bu environment'e **yeni bir package** kurduğunuz her seferinde environment'i yeniden **aktif edin**.
Böylece, o package'in kurduğu bir **terminal (CLI) programı** kullanıyorsanız, global olarak kurulu (ve muhtemelen ihtiyacınız olandan farklı bir versiyona sahip) başka bir program yerine, virtual environment'inizdeki programı kullanmış olursunuz.
///
## Virtual Environment'in Aktif Olduğunu Kontrol Edin { #check-the-virtual-environment-is-active }
Virtual environment'in aktif olduğunu (bir önceki komutun çalıştığını) kontrol edin.
/// tip | İpucu
Bu **opsiyoneldir**; ancak her şeyin beklendiği gibi çalıştığını ve hedeflediğiniz virtual environment'i kullandığınızı **kontrol etmek** için iyi bir yöntemdir.
///
//// tab | Linux, macOS, Windows Bash
```console
$ which python
/home/user/code/awesome-project/.venv/bin/python
```
Eğer `python` binary'sini projenizin içinde (bu örnekte `awesome-project`) `.venv/bin/python` yolunda gösteriyorsa, tamamdır. 🎉
////
//// tab | Windows PowerShell
```console
$ Get-Command python
C:\Users\user\code\awesome-project\.venv\Scripts\python
```
Eğer `python` binary'sini projenizin içinde (bu örnekte `awesome-project`) `.venv\Scripts\python` yolunda gösteriyorsa, tamamdır. 🎉
////
## `pip`'i Yükseltin { #upgrade-pip }
/// tip | İpucu
`uv` kullanıyorsanız, `pip` yerine onunla kurulum yaparsınız; dolayısıyla `pip`'i yükseltmeniz gerekmez. 😎
///
Package'leri kurmak için `pip` kullanıyorsanız (Python ile varsayılan olarak gelir), en güncel sürüme **yükseltmeniz** gerekir.
Bir package kurarken görülen birçok garip hata, önce `pip`'i yükseltince çözülür.
/// tip | İpucu
Bunu genelde virtual environment'i oluşturduktan hemen sonra **bir kez** yaparsınız.
///
Virtual environment'in aktif olduğundan emin olun (yukarıdaki komutla) ve sonra şunu çalıştırın:
```console
$ python -m pip install --upgrade pip
---> 100%
```
/// tip | İpucu
Bazen pip'i yükseltmeye çalışırken **`No module named pip`** hatası alabilirsiniz.
Böyle olursa, aşağıdaki komutla pip'i kurup yükseltin:
```console
$ python -m ensurepip --upgrade
---> 100%
```
Bu komut pip kurulu değilse kurar ve ayrıca kurulu pip sürümünün `ensurepip` içinde bulunan sürüm kadar güncel olmasını garanti eder.
///
## `.gitignore` Ekleyin { #add-gitignore }
**Git** kullanıyorsanız (kullanmalısınız), `.venv` içindeki her şeyi Git'ten hariç tutmak için bir `.gitignore` dosyası ekleyin.
/// tip | İpucu
Virtual environment'i `uv` ile oluşturduysanız, bunu zaten sizin için yaptı; bu adımı atlayabilirsiniz. 😎
///
/// tip | İpucu
Bunu virtual environment'i oluşturduktan hemen sonra **bir kez** yapın.
///
```console
$ echo "*" > .venv/.gitignore
```
/// details | Bu komut ne anlama geliyor
* `echo "*"`: terminale `*` metnini "yazar" (sonraki kısım bunu biraz değiştiriyor)
* `>`: `>` işaretinin solundaki komutun terminale yazdıracağı çıktı, ekrana basılmak yerine sağ taraftaki dosyaya yazılsın
* `.gitignore`: metnin yazılacağı dosyanın adı
Git'te `*` "her şey" demektir. Yani `.venv` klasörü içindeki her şeyi ignore eder.
Bu komut, içeriği şu olan bir `.gitignore` dosyası oluşturur:
```gitignore
*
```
///
## Package'leri Kurun { #install-packages }
Environment'i aktif ettikten sonra, içine package kurabilirsiniz.
/// tip | İpucu
Projede ihtiyaç duyduğunuz package'leri ilk kez kurarken veya yükseltirken bunu **bir kez** yapın.
Bir sürümü yükseltmeniz veya yeni bir package eklemeniz gerekirse **tekrar** yaparsınız.
///
### Package'leri Doğrudan Kurun { #install-packages-directly }
Acele ediyorsanız ve projenizin package gereksinimlerini bir dosyada belirtmek istemiyorsanız, doğrudan kurabilirsiniz.
/// tip | İpucu
Programınızın ihtiyaç duyduğu package'leri ve versiyonlarını bir dosyada tutmak (ör. `requirements.txt` veya `pyproject.toml`) (çok) iyi bir fikirdir.
///
//// tab | `pip`
```console
$ pip install "fastapi[standard]"
---> 100%
```
////
//// tab | `uv`
Eğer `uv` varsa:
```console
$ uv pip install "fastapi[standard]"
---> 100%
```
////
### `requirements.txt`'ten Kurun { #install-from-requirements-txt }
Bir `requirements.txt` dosyanız varsa, içindeki package'leri kurmak için artık onu kullanabilirsiniz.
//// tab | `pip`
```console
$ pip install -r requirements.txt
---> 100%
```
////
//// tab | `uv`
Eğer `uv` varsa:
```console
$ uv pip install -r requirements.txt
---> 100%
```
////
/// details | `requirements.txt`
Bazı package'ler içeren bir `requirements.txt` şöyle görünebilir:
```requirements.txt
fastapi[standard]==0.113.0
pydantic==2.8.0
```
///
## Programınızı Çalıştırın { #run-your-program }
Virtual environment'i aktif ettikten sonra programınızı çalıştırabilirsiniz; program, virtual environment'in içindeki Python'ı ve oraya kurduğunuz package'leri kullanır.
```console
$ python main.py
Hello World
```
## Editörünüzü Yapılandırın { #configure-your-editor }
Muhtemelen bir editör kullanırsınız; otomatik tamamlamayı ve satır içi hataları alabilmek için, editörünüzü oluşturduğunuz aynı virtual environment'i kullanacak şekilde yapılandırdığınızdan emin olun (muhtemelen otomatik algılar).
Örneğin:
* VS Code
* PyCharm
/// tip | İpucu
Bunu genelde yalnızca **bir kez**, virtual environment'i oluşturduğunuzda yapmanız gerekir.
///
## Virtual Environment'i Devre Dışı Bırakın { #deactivate-the-virtual-environment }
Projeniz üzerinde işiniz bittiğinde virtual environment'i **deactivate** edebilirsiniz.
```console
$ deactivate
```
Böylece `python` çalıştırdığınızda, o virtual environment içinden (ve oraya kurulu package'lerle) çalıştırmaya çalışmaz.
## Çalışmaya Hazırsınız { #ready-to-work }
Artık projeniz üzerinde çalışmaya başlayabilirsiniz.
/// tip | İpucu
Yukarıdaki her şeyin aslında ne olduğunu anlamak ister misiniz?
Okumaya devam edin. 👇🤓
///
## Neden Virtual Environment { #why-virtual-environments }
FastAPI ile çalışmak için Python kurmanız gerekir.
Sonrasında FastAPI'yi ve kullanmak istediğiniz diğer tüm **package**'leri **kurmanız** gerekir.
Package kurmak için genelde Python ile gelen `pip` komutunu (veya benzeri alternatifleri) kullanırsınız.
Ancak `pip`'i doğrudan kullanırsanız, package'ler **global Python environment**'ınıza (Python'ın global kurulumuna) yüklenir.
### Problem { #the-problem }
Peki package'leri global Python environment'a kurmanın sorunu ne?
Bir noktada, muhtemelen **farklı package**'lere bağımlı birçok farklı program yazacaksınız. Ayrıca üzerinde çalıştığınız bazı projeler, aynı package'in **farklı versiyonlarına** ihtiyaç duyacak. 😱
Örneğin `philosophers-stone` adında bir proje oluşturduğunuzu düşünün; bu program, `harry` adlı başka bir package'e **`1` versiyonu ile** bağlı. Yani `harry`'yi kurmanız gerekir.
```mermaid
flowchart LR
stone(philosophers-stone) -->|requires| harry-1[harry v1]
```
Sonra daha ileri bir zamanda `prisoner-of-azkaban` adlı başka bir proje oluşturuyorsunuz; bu proje de `harry`'ye bağlı, fakat bu proje **`harry` versiyon `3`** istiyor.
```mermaid
flowchart LR
azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3]
```
Şimdi sorun şu: package'leri local bir **virtual environment** yerine global (global environment) olarak kurarsanız, `harry`'nin hangi versiyonunu kuracağınıza karar vermek zorunda kalırsınız.
`philosophers-stone`'u çalıştırmak istiyorsanız önce `harry` versiyon `1`'i kurmanız gerekir; örneğin:
```console
$ pip install "harry==1"
```
Sonuç olarak global Python environment'ınızda `harry` versiyon `1` kurulu olur.
```mermaid
flowchart LR
subgraph global[global env]
harry-1[harry v1]
end
subgraph stone-project[philosophers-stone project]
stone(philosophers-stone) -->|requires| harry-1
end
```
Fakat `prisoner-of-azkaban`'ı çalıştırmak istiyorsanız, `harry` versiyon `1`'i kaldırıp `harry` versiyon `3`'ü kurmanız gerekir (ya da sadece `3`'ü kurmak, otomatik olarak `1`'i kaldırabilir).
```console
$ pip install "harry==3"
```
Sonuç olarak global Python environment'ınızda `harry` versiyon `3` kurulu olur.
Ve `philosophers-stone`'u tekrar çalıştırmaya kalkarsanız, `harry` versiyon `1`'e ihtiyaç duyduğu için **çalışmama** ihtimali vardır.
```mermaid
flowchart LR
subgraph global[global env]
harry-1[harry v1]
style harry-1 fill:#ccc,stroke-dasharray: 5 5
harry-3[harry v3]
end
subgraph stone-project[philosophers-stone project]
stone(philosophers-stone) -.-x|⛔️| harry-1
end
subgraph azkaban-project[prisoner-of-azkaban project]
azkaban(prisoner-of-azkaban) --> |requires| harry-3
end
```
/// tip | İpucu
Python package'lerinde **yeni versiyonlarda** **breaking change**'lerden kaçınmak oldukça yaygındır; ancak yine de daha güvenlisi, yeni versiyonları bilinçli şekilde kurmak ve mümkünse test'leri çalıştırıp her şeyin doğru çalıştığını doğrulamaktır.
///
Şimdi bunu, **projelerinizin bağımlı olduğu** daha **birçok** başka **package** ile birlikte düşünün. Yönetmesi epey zorlaşır. Sonunda bazı projeleri package'lerin **uyumsuz versiyonlarıyla** çalıştırıp, bir şeylerin neden çalışmadığını anlamamak gibi durumlara düşebilirsiniz.
Ayrıca işletim sisteminize (örn. Linux, Windows, macOS) bağlı olarak Python zaten kurulu gelmiş olabilir. Bu durumda, sisteminizin **ihtiyaç duyduğu** bazı package'ler belirli versiyonlarla önceden kurulu olabilir. Global Python environment'a package kurarsanız, işletim sistemiyle gelen bazı programları **bozma** ihtimaliniz olabilir.
## Package'ler Nereye Kuruluyor { #where-are-packages-installed }
Python'ı kurduğunuzda, bilgisayarınızda bazı dosyalar içeren klasörler oluşturulur.
Bu klasörlerin bir kısmı, kurduğunuz tüm package'leri barındırmaktan sorumludur.
Şunu çalıştırdığınızda:
```console
// Don't run this now, it's just an example 🤓
$ pip install "fastapi[standard]"
---> 100%
```
Bu, FastAPI kodunu içeren sıkıştırılmış bir dosyayı genellikle PyPI'dan indirir.
Ayrıca FastAPI'nin bağımlı olduğu diğer package'ler için de dosyaları **indirir**.
Sonra tüm bu dosyaları **açar (extract)** ve bilgisayarınızdaki bir klasöre koyar.
Varsayılan olarak bu indirilip çıkarılan dosyaları, Python kurulumunuzla birlikte gelen klasöre yerleştirir; yani **global environment**'a.
## Virtual Environment Nedir { #what-are-virtual-environments }
Global environment'da tüm package'leri bir arada tutmanın sorunlarına çözüm, çalıştığınız her proje için ayrı bir **virtual environment** kullanmaktır.
Virtual environment, global olana çok benzeyen bir **klasördür**; bir projenin ihtiyaç duyduğu package'leri buraya kurarsınız.
Böylece her projenin kendi virtual environment'i (`.venv` klasörü) ve kendi package'leri olur.
```mermaid
flowchart TB
subgraph stone-project[philosophers-stone project]
stone(philosophers-stone) --->|requires| harry-1
subgraph venv1[.venv]
harry-1[harry v1]
end
end
subgraph azkaban-project[prisoner-of-azkaban project]
azkaban(prisoner-of-azkaban) --->|requires| harry-3
subgraph venv2[.venv]
harry-3[harry v3]
end
end
stone-project ~~~ azkaban-project
```
## Virtual Environment'i Aktif Etmek Ne Demek { #what-does-activating-a-virtual-environment-mean }
Bir virtual environment'i örneğin şununla aktif ettiğinizde:
//// tab | Linux, macOS
```console
$ source .venv/bin/activate
```
////
//// tab | Windows PowerShell
```console
$ .venv\Scripts\Activate.ps1
```
////
//// tab | Windows Bash
Ya da Windows'ta Bash kullanıyorsanız (örn. Git Bash):
```console
$ source .venv/Scripts/activate
```
////
Bu komut, sonraki komutlarda kullanılabilecek bazı [environment variable](environment-variables.md){.internal-link target=_blank}'ları oluşturur veya değiştirir.
Bunlardan biri `PATH` değişkenidir.
/// tip | İpucu
`PATH` environment variable hakkında daha fazla bilgiyi [Environment Variables](environment-variables.md#path-environment-variable){.internal-link target=_blank} bölümünde bulabilirsiniz.
///
Bir virtual environment'i aktive etmek, onun `.venv/bin` (Linux ve macOS'ta) veya `.venv\Scripts` (Windows'ta) yolunu `PATH` environment variable'ına ekler.
Diyelim ki environment'i aktive etmeden önce `PATH` değişkeni şöyleydi:
//// tab | Linux, macOS
```plaintext
/usr/bin:/bin:/usr/sbin:/sbin
```
Bu, sistemin programları şu klasörlerde arayacağı anlamına gelir:
* `/usr/bin`
* `/bin`
* `/usr/sbin`
* `/sbin`
////
//// tab | Windows
```plaintext
C:\Windows\System32
```
Bu, sistemin programları şurada arayacağı anlamına gelir:
* `C:\Windows\System32`
////
Virtual environment'i aktive ettikten sonra `PATH` değişkeni şuna benzer hale gelir:
//// tab | Linux, macOS
```plaintext
/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
Bu, sistemin artık programları önce şurada aramaya başlayacağı anlamına gelir:
```plaintext
/home/user/code/awesome-project/.venv/bin
```
diğer klasörlere bakmadan önce.
Dolayısıyla terminale `python` yazdığınızda, sistem Python programını şurada bulur:
```plaintext
/home/user/code/awesome-project/.venv/bin/python
```
ve onu kullanır.
////
//// tab | Windows
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32
```
Bu, sistemin artık programları önce şurada aramaya başlayacağı anlamına gelir:
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts
```
diğer klasörlere bakmadan önce.
Dolayısıyla terminale `python` yazdığınızda, sistem Python programını şurada bulur:
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts\python
```
ve onu kullanır.
////
Önemli bir detay: virtual environment yolu `PATH` değişkeninin **en başına** eklenir. Sistem, mevcut başka herhangi bir Python'ı bulmadan **önce** bunu bulur. Böylece `python` çalıştırdığınızda, başka bir `python` (örneğin global environment'tan gelen `python`) yerine **virtual environment'taki** Python kullanılır.
Virtual environment'i aktive etmek birkaç şeyi daha değiştirir; ancak yaptığı en önemli işlerden biri budur.
## Virtual Environment'i Kontrol Etmek { #checking-a-virtual-environment }
Bir virtual environment'in aktif olup olmadığını örneğin şununla kontrol ettiğinizde:
//// tab | Linux, macOS, Windows Bash
```console
$ which python
/home/user/code/awesome-project/.venv/bin/python
```
////
//// tab | Windows PowerShell
```console
$ Get-Command python
C:\Users\user\code\awesome-project\.venv\Scripts\python
```
////
Bu, kullanılacak `python` programının **virtual environment'in içindeki** Python olduğu anlamına gelir.
Linux ve macOS'ta `which`, Windows PowerShell'de ise `Get-Command` kullanırsınız.
Bu komutun çalışma mantığı şudur: `PATH` environment variable içindeki **her yolu sırayla** dolaşır, `python` adlı programı arar. Bulduğunda, size o programın **dosya yolunu** gösterir.
En önemli kısım şu: `python` dediğinizde çalışacak olan "`python`" tam olarak budur.
Yani doğru virtual environment'da olup olmadığınızı doğrulayabilirsiniz.
/// tip | İpucu
Bir virtual environment'i aktive etmek kolaydır; sonra o Python ile kalıp **başka bir projeye geçmek** de kolaydır.
Bu durumda ikinci proje, başka bir projenin virtual environment'ından gelen **yanlış Python**'ı kullandığınız için **çalışmayabilir**.
Hangi `python`'ın kullanıldığını kontrol edebilmek bu yüzden faydalıdır. 🤓
///
## Neden Virtual Environment'i Deactivate Edelim { #why-deactivate-a-virtual-environment }
Örneğin `philosophers-stone` projesi üzerinde çalışıyor olabilirsiniz; **o virtual environment'i aktive eder**, package kurar ve o environment ile çalışırsınız.
Sonra **başka bir proje** olan `prisoner-of-azkaban` üzerinde çalışmak istersiniz.
O projeye gidersiniz:
```console
$ cd ~/code/prisoner-of-azkaban
```
Eğer `philosophers-stone` için olan virtual environment'i deactivate etmezseniz, terminalde `python` çalıştırdığınızda `philosophers-stone`'dan gelen Python'ı kullanmaya çalışır.
```console
$ cd ~/code/prisoner-of-azkaban
$ python main.py
// Error importing sirius, it's not installed 😱
Traceback (most recent call last):
File "main.py", line 1, in
import sirius
```
Ama virtual environment'i deactivate edip `prisoner-of-askaban` için yeni olanı aktive ederseniz, `python` çalıştırdığınızda `prisoner-of-azkaban` içindeki virtual environment'dan gelen Python kullanılır.
```console
$ cd ~/code/prisoner-of-azkaban
// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎
$ deactivate
// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀
$ source .venv/bin/activate
// Now when you run python, it will find the package sirius installed in this virtual environment ✨
$ python main.py
I solemnly swear 🐺
```
## Alternatifler { #alternatives }
Bu, başlamanız için basit bir rehber ve alttaki mekanizmaların nasıl çalıştığını öğretmeyi amaçlıyor.
Virtual environment'leri, package bağımlılıklarını (requirements) ve projeleri yönetmek için birçok **alternatif** vardır.
Hazır olduğunuzda ve package bağımlılıkları, virtual environment'ler vb. dahil **tüm projeyi yönetmek** için bir tool kullanmak istediğinizde, uv'yi denemenizi öneririm.
`uv` birçok şey yapabilir, örneğin:
* Sizin için **Python kurabilir**, farklı sürümler dahil
* Projelerinizin **virtual environment**'ini yönetebilir
* **Package** kurabilir
* Projeniz için package **bağımlılıklarını ve versiyonlarını** yönetebilir
* Bağımlılıkları dahil, kurulacak package ve versiyonların **tam (exact)** bir setini garanti edebilir; böylece geliştirirken bilgisayarınızda çalıştırdığınız projeyi production'da da birebir aynı şekilde çalıştırabileceğinizden emin olursunuz; buna **locking** denir
* Ve daha birçok şey
## Sonuç { #conclusion }
Buradaki her şeyi okuduysanız ve anladıysanız, artık birçok geliştiriciden **çok daha fazla** virtual environment bilgisine sahipsiniz. 🤓
Bu detayları bilmek, ileride karmaşık görünen bir sorunu debug ederken büyük olasılıkla işinize yarayacak; çünkü **altta nasıl çalıştığını** biliyor olacaksınız. 😎