Defter gibi çalışmak
Veri analistinin günü çoğu zaman bir soruyla başlar: "Geçen ay İzmir'de iade oranı neden arttı?" Bu tür sorularda kodu baştan sona yazıp çalıştırmak yerine adım adım ilerlemek istersin: veriyi oku, ilk beş satıra bak, bir filtre dene, grafiği çiz, yorum yaz. Jupyter Notebook tam bunun için var. Kod, çıktı, grafik ve açıklama metni tek bir belgede, hücre (cell) denen bloklar hâlinde yan yana durur. Kurulum ve araçlar dersinde Jupyter'a kısaca bakmıştın; bu derste notebook'u bilinçli kullanmayı, en tehlikeli tuzağı (gizli durum), Colab'i, conda'yı ve notebook'tan gerçek bir betiğe geçişi öğreneceksin.
Kurulum ve ilk açılış
Jupyter bir Python paketidir; projenin sanal ortamına (virtual environment) kurulur:
python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1 python -m pip install jupyterlab pandas matplotlib jupyter lab # tarayıcıda http://localhost:8888 açılır
JupyterLab modern arayüzdür (dosya gezgini, sekmeler, terminal); klasik Notebook arayüzü jupyter notebook ile açılır. İkisi de aynı .ipynb dosyalarını kullanır. Terminali kapatırsan sunucu da kapanır. Arka planda çalışan şeye çekirdek (kernel) denir: kodunu çalıştıran Python sürecidir ve değişkenleri bellekte tutar.
Hücre türleri ve kısayollar
| Hücre türü | Ne içerir | Çalıştırınca |
|---|---|---|
| Code | Python kodu | Çekirdekte çalışır, altında çıktı görünür; son ifadenin değeri otomatik gösterilir |
| Markdown | Başlık, liste, tablo, formül (# Başlık, **kalın**) | Biçimlendirilmiş metne dönüşür |
| Raw | İşlenmeyen düz metin | Hiçbir şey; dönüştürme araçları için |
Jupyter'da iki mod vardır: düzenleme modu (hücrenin içine yazarsın, kenar yeşil/mavi) ve komut modu (Esc ile girilir; hücrelerin kendisini yönetirsin).
| Tuş | Mod | Eylem |
|---|---|---|
| Shift+Enter | Her ikisi | Hücreyi çalıştır, sonrakine geç |
| Ctrl+Enter | Her ikisi | Hücreyi çalıştır, yerinde kal |
| Alt+Enter | Her ikisi | Çalıştır ve altına yeni hücre ekle |
| A / B | Komut | Üste / alta hücre ekle |
| D, D | Komut | Hücreyi sil |
| M / Y | Komut | Markdown'a / koda çevir |
| 0, 0 | Komut | Çekirdeği yeniden başlat |
En tehlikeli tuzak: çalıştırma sırası ve gizli durum
Hücrelerin solundaki [5] gibi sayı çalıştırma sayacıdır (execution count): o hücrenin çekirdekte kaçıncı sırada çalıştığını gösterir. Notebook'u yukarıdan aşağı okursun ama çekirdek hücreleri senin tıkladığın sırayla çalıştırır. Bir değişkeni tanımlayan hücreyi silsen bile değişken bellekte yaşamaya devam eder. Buna gizli durum (hidden state) denir: notebook sende çalışır, ekip arkadaşında ya da yarın sabah çekirdeği yeniden başlattığında çalışmaz.
hucreler = {
1: "kur = 32.5",
2: "tutar_tl = 1000 * kur",
3: "kur = 34.0",
}
for sira in ([1, 2, 3], [1, 3, 2]):
cekirdek = {} # yeni bir çekirdek
for no in sira:
exec(hucreler[no], cekirdek)
print(f"Sıra {sira}: tutar_tl = {cekirdek['tutar_tl']}")
Aynı üç hücre, iki farklı sırada iki farklı sonuç verdi. Notebook'a bakan biri hangi sırada çalıştırıldığını göremez. Korunmanın tek güvenilir yolu: paylaşmadan, kaydetmeden ve sonuca güvenmeden önce Kernel → Restart Kernel and Run All Cells. Yukarıdan aşağı hatasız çalışıyorsa notebook'un "temiz"dir.
Sihirli komutlar (magic commands)
IPython çekirdeği, Python olmayan bazı özel komutlar sunar. Tek % satır sihridir (yalnız o satıra etki eder), çift %% hücre sihridir (hücrenin ilk satırında olmalı ve tüm hücreye etki eder), ! ise satırı işletim sistemi kabuğunda çalıştırır.
%timeit sum(range(10_000)) # satırı defalarca çalıştırıp ortalama süre %%time # (hücrenin ilk satırı) tüm hücrenin süresi %who # tanımlı değişkenler %pwd # çalışma dizini %pip install openpyxl # paketi BU çekirdeğin ortamına kur !ls veri/ # kabuk komutu (Windows'ta !dir) %load_ext autoreload %autoreload 2 # düzenlediğin .py modüllerini otomatik yeniden yükle
!pip install kabukta PATH'teki ilk pip'i çalıştırır; o pip çekirdeğin Python'ına ait olmayabilir ve "kurdum ama ModuleNotFoundError" sorunu doğar. %pip install paketi her zaman çalışan çekirdeğin ortamına kurar.Sihirli komutlar yalnız Jupyter'da çalışır; .py dosyasında SyntaxError verir. Betikte aynı ölçümü timeit modülüyle yaparsın:
import timeit
liste_yontemi = timeit.timeit("sum([x * x for x in range(1000)])", number=2000)
uretec_yontemi = timeit.timeit("sum(x * x for x in range(1000))", number=2000)
print(f"Liste : {liste_yontemi:.3f} sn / 2000 tekrar")
print(f"Üreteç : {uretec_yontemi:.3f} sn / 2000 tekrar")
print("İkisi de aynı sonucu verir:", sum([x * x for x in range(1000)]) == sum(x * x for x in range(1000)))
Anaconda ve Miniconda
Anaconda, Python'ı yüzlerce bilimsel paketle birlikte getiren bir dağıtımdır; Miniconda ise yalnız Python ve conda paket yöneticisini kurar, gerisini sen eklersin. conda, pip'ten farklı olarak Python dışı bağımlılıkları da (C kütüphaneleri, CUDA, hatta R) yönetir ve Python sürümünün kendisini ortam başına kurar.
conda create -n analiz python=3.12 pandas matplotlib jupyterlab conda activate analiz conda install -c conda-forge scikit-learn pip install bir-paket # conda'da olmayan paket için, EN SON conda env export --from-history > environment.yml conda env create -f environment.yml # başka makinede aynı ortam conda deactivate
| conda | pip + venv | |
|---|---|---|
| Python sürümü | Ortam başına kurar | Var olan Python'ı kullanır |
| Python dışı bağımlılık | Yönetir (C, CUDA, GDAL) | Yönetemez; tekerlek (wheel) içinde gelmeli |
| Paket kaynağı | Anaconda kanalları, conda-forge | PyPI (en geniş katalog) |
| Ortam dosyası | environment.yml | requirements.txt / pyproject.toml |
| Hız ve boyut | Daha ağır | Hafif |
Kurallar: bir ortamda önce conda ile kurabildiğin her şeyi kur, pip'i en son kullan; pip'ten sonra tekrar conda install yapmak ortamı tutarsız bırakabilir. Kurumsal kullanımda Anaconda'nın varsayılan kanalının lisans koşullarını kontrol et; ücretsiz conda-forge kanalını kullanan Miniforge yaygın bir alternatiftir. Bir conda ortamını Jupyter'da çekirdek olarak görmek için ortam içinde python -m ipykernel install --user --name analiz çalıştır.
Google Colab
Colab, Google'ın tarayıcıda çalışan ücretsiz notebook hizmetidir: kurulum yok, pandas ve scikit-learn hazır, sınırlı süreli ücretsiz GPU bile var. Ama makine geçicidir. Oturum bir süre boşta kalınca ya da süre sınırı dolunca çalışma zamanı (runtime) sıfırlanır: /content altına yüklediğin dosyalar, kurduğun paketler ve bellekteki değişkenler gider. Kalıcı dosyalar için Google Drive bağlanır:
from google.colab import drive
drive.mount("/content/drive")
import pandas as pd
df = pd.read_csv("/content/drive/MyDrive/anadolu/siparisler.csv")
from google.colab import files
yuklenen = files.upload() # bilgisayardan dosya seç (oturum sonunda silinir)
files.download("rapor.xlsx") # sonucu indir
%pip install -q openpyxl # her yeni oturumda yeniden gerekir
Runtime → Change runtime type menüsünden GPU seçilir. Parola ve API anahtarlarını hücreye yazma; Colab'in sol panelindeki Secrets (anahtar simgesi) bölümüne koyup google.colab.userdata.get("ANAHTAR") ile oku. Paylaşılan bir notebook'a yazılmış anahtar, linki gören herkesindir.
.ipynb aslında JSON'dur
Notebook dosyası, hücreleri ve çıktıları tutan bir JSON belgesidir. Bu yüzden git farkları (diff) okunaksızdır: tek satır kod değişse bile çıktılar, sayaçlar ve gömülü grafikler (base64 metin) değişir. Yapıyı bilmek, notebook'ları Python ile işlemeni sağlar:
import json
nb_metni = """{
"nbformat": 4, "nbformat_minor": 5, "metadata": {},
"cells": [
{"cell_type": "markdown", "metadata": {}, "source": ["# İade analizi\\n", "Ekim 2026"]},
{"cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [],
"source": ["import pandas as pd\\n", "df = pd.read_csv('iadeler.csv')"]},
{"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [],
"source": "%timeit df.groupby('sehir').size()"}
]
}"""
nb = json.loads(nb_metni)
for i, h in enumerate(nb["cells"]):
kaynak = h["source"] if isinstance(h["source"], str) else "".join(h["source"])
sayac = h.get("execution_count", "-")
print(f"[{i}] {h['cell_type']:8} sayaç={sayac} | {kaynak.splitlines()[0]}")
source alanı satır listesi ya da tek metin olabilir; ikisini de desteklemelisin. Bu notebook'ta ikinci kod hücresinin sayacı (1) birincininkinden (2) küçük: sıra bozuk!
Notebook'tan .py dosyasına
Keşif bittiğinde düzenli çalışacak kod (günlük rapor, model eğitimi) betiğe ve modüllere taşınır. İlk adım otomatik dönüştürmedir:
jupyter nbconvert --to script iade_analizi.ipynb # iade_analizi.py üretir jupyter nbconvert --to html iade_analizi.ipynb # paylaşmak için HTML rapor jupyter nbconvert --to notebook --execute --inplace iade_analizi.ipynb # baştan çalıştır
Üretilen .py dosyasında markdown hücreleri yorum olur, sihirli komutlar get_ipython() çağrılarına dönüşür (bunları elle temizlemen gerekir). Ardından kodu fonksiyonlara böl, sabit dosya yollarını parametre yap ve test yaz. VS Code ve Jupytext'in kullandığı yüzde biçimi (percent format) iki dünyayı birleştirir: # %% ile ayrılmış sıradan bir .py dosyası, VS Code'da hücre hücre çalıştırılabilir:
hucreler = [
("markdown", "# Şehir bazında iade\nEkim verisi"),
("code", "iadeler = {'İzmir': 41, 'Ankara': 28}"),
("code", "print(max(iadeler, key=iadeler.get))"),
]
parcalar = []
for tur, kaynak in hucreler:
if tur == "markdown":
yorum = "\n".join("# " + s for s in kaynak.splitlines())
parcalar.append("# %% [markdown]\n" + yorum)
else:
parcalar.append("# %%\n" + kaynak)
betik = "\n\n".join(parcalar)
print(betik)
print("---- çalıştırılıyor ----")
exec(betik)
Notebook ne zaman uygun değil?
- Üretimde düzenli çalışan işler: zamanlanmış rapor, API, ETL. Betik + modül + test kullan.
- Ekipçe geliştirilen kod: JSON farkları kod incelemesini (code review) zorlaştırır; ortak fonksiyonları .py modüllerine taşı, notebook'tan içe aktar.
- Uzun süren hesaplar: tarayıcı sekmesi kapanınca ya da Colab oturumu düşünce iş kaybolabilir.
- Test edilmesi gereken mantık: notebook hücreleri birim testine uygun değildir.
Notebook'un parladığı yerler: keşifsel veri analizi, grafikle anlatılan raporlar, eğitim materyali, bir modelin hızlı denenmesi.
VS Code'da .ipynb
Jupyter eklentisi kuruluysa VS Code .ipynb dosyalarını doğrudan açar. Sağ üstteki Select Kernel düğmesiyle projenin .venv'ini seç (ortamda ipykernel yoksa VS Code kurmayı önerir). Üst çubuktaki Variables düğmesi tüm değişkenleri tablo olarak gösterir; hücrelerde kesme noktası koyup hata ayıklayabilirsin. VS Code ile Python dersinde gördüğün yorumlayıcı seçimi burada çekirdek seçimine karşılık gelir.
Belirti → neden → çözüm
| Belirti | Neden | Çözüm |
|---|---|---|
!pip install sonrası ModuleNotFoundError | Paket çekirdekten farklı bir Python'a kuruldu | %pip install; ya da doğru çekirdeği seç |
Dün çalışan notebook bugün NameError | Gizli durum: silinen ya da sonra çalıştırılan hücreye bağımlılık | Restart and Run All; eksik tanımı doğru hücreye koy |
| "Kernel died / restarting" | Bellek yetmedi (dev DataFrame) ya da yerel kütüphane çöktü | Veriyi parça parça oku, gereksiz değişkenleri del et |
| Colab'de dosyalarım kayboldu | Runtime sıfırlandı; /content geçicidir | Drive bağla, sonuçları Drive'a yaz |
Colab'de FileNotFoundError Drive yolunda | Yol yanlış ya da Drive bağlanmadı | /content/drive/MyDrive/...; önce drive.mount |
.py dosyasında %timeit SyntaxError | Sihirli komutlar yalnız IPython'da | timeit modülünü kullan |
| Notebook git'te dev boyutlu, farklar okunmuyor | Çıktılar ve grafikler dosyada saklanıyor | Kaydetmeden önce çıktıları temizle; nbstripout |
asyncio.run() "cannot be called from a running event loop" | Jupyter'da zaten bir olay döngüsü çalışıyor | Hücrede doğrudan await kullan |
| Jupyter yeni kurduğun conda ortamını görmüyor | Ortam çekirdek olarak kaydedilmemiş | python -m ipykernel install --user --name ortam |
src/analiz/ altındaki modüllere taşınıyor, notebook ise bu fonksiyonları içe aktaran kısa bir anlatıma dönüşüyor. Depoya girmeden önce bir pre-commit kancası (nbstripout) çıktıları temizliyor; CI'da nbconvert --execute her notebook'u baştan çalıştırıp gizli durum hatalarını yakalıyor. Yönetime giden aylık rapor ise papermill ile parametreli çalıştırılıp HTML'e çevriliyor.Derste notebook'u .py'ye ve tek bir HTML'e çevirmeyi, papermill'in ne yaptığını gördün. Bu bölüm o adımları bir rapor hattına dönüştürüyor: kodu gizlenmiş, okunur bir HTML rapor; Quarto ile yayın kalitesinde belge; papermill ile her şehir için ayrı rapor üreten tek bir şablon notebook. Örnek, Anadolu Market'in gerçek sipariş verisinden şehir raporu.
nbconvert ile yöneticiye uygun HTML
Yönetici kodu değil sonuçları görmek ister. nbconvert, hücreleri etiketlere (tags) göre süzebilir: JupyterLab'de sağ paneldeki "Property Inspector"dan hücreye remove_input (kodu gizle, çıktıyı göster) ya da remove_cell (tümünü gizle) etiketi verirsin.
jupyter nbconvert rapor.ipynb --to html --no-input # tüm kodları gizle
jupyter nbconvert rapor.ipynb --to html --execute \
--TagRemovePreprocessor.remove_input_tags remove_input \
--TagRemovePreprocessor.remove_cell_tags remove_cell # etikete göre
jupyter nbconvert rapor.ipynb --to webpdf --no-input # PDF (pip install "nbconvert[webpdf]")
--execute raporu çevirmeden önce notebook'u baştan çalıştırır; böylece HTML'deki sayıların gerçekten o koddan çıktığı garanti olur. Grafikler HTML'in içine gömülür, dosyayı e-postayla göndermek yeter.
Quarto: notebook'tan belgeye
Quarto, notebook'ları ve .qmd (Markdown + kod) dosyalarını HTML, PDF, Word ve sunuma çeviren açık kaynaklı bir yayın aracıdır. Ayarlar en baştaki YAML başlığında durur; hücre seçenekleri #| ile başlayan yorumlardır.
---
title: "İzmir satış raporu"
author: "Analiz ekibi"
format:
html:
code-fold: true # kodu katlanabilir yap
toc: true
embed-resources: true # tek dosya
execute:
echo: false # varsayılan: kodu gösterme
---
```{python}
#| tags: [parameters]
sehir = "İzmir"
```
```{python}
#| label: fig-ciro
#| fig-cap: "Yıllara göre teslim edilen ciro"
grafik_ciz(sehir)
```
quarto render rapor.qmd # HTML quarto render rapor.ipynb --to pdf # notebook da doğrudan çevrilir quarto render rapor.qmd -P sehir:Ankara --output ankara.html # parametreyle
papermill: tek şablon, çok rapor
papermill, parameters etiketli hücrenin hemen altına "injected-parameters" adlı yeni bir hücre ekleyerek değerleri ezer; şablon notebook'taki varsayılanlar bozulmaz. Çalışan her kopya çıktılarıyla birlikte kaydedilir, böylece hangi raporun hangi parametreyle üretildiği iz bırakır.
import papermill as pm
for sehir in ["İstanbul", "İzmir", "Ankara"]:
cikti = f"raporlar/{sehir}.ipynb"
pm.execute_notebook("sablon.ipynb", cikti, parameters={"sehir": sehir, "yil": 2024})
# ardından: jupyter nbconvert cikti --to html --no-input
Şablonun kalbi, parametreye göre çalışan sıradan bir fonksiyondur. Aynı mantığı tarayıcıda çalıştırabilirsin:
import veri
conn = veri.baglan("anadolu_market", tablolar=["orders", "order_items", "customers"])
def sehir_raporu(sehir):
sorgu = """
SELECT substr(o.order_date, 1, 4) AS yil, COUNT(DISTINCT o.order_id),
ROUND(SUM(oi.quantity * oi.unit_price * (1 - oi.discount)), 2)
FROM orders o JOIN customers c USING (customer_id) JOIN order_items oi USING (order_id)
WHERE o.status = 'delivered' AND c.city = ?
GROUP BY yil ORDER BY yil"""
return conn.execute(sorgu, (sehir,)).fetchall()
for sehir in ["İzmir", "Ankara"]: # papermill döngüsünün karşılığı
print(sehir, sehir_raporu(sehir))
| Araç | Güçlü yanı | Ne zaman? |
|---|---|---|
| nbconvert | Jupyter ile gelir, hızlı, etiketle süzme | Ekibe hızlı HTML/PDF |
| Quarto | Yayın kalitesi, çapraz referans, web sitesi ve sunum | Müşteriye rapor, blog, portföy sitesi |
| papermill | Parametreli toplu çalıştırma, iz bırakır | Her şehir/ay için aynı rapor; zamanlanmış raporlar |
pip install nbconvert papermill; Quarto'yu quarto.org'dan kur (Python paketi değil, ayrı bir programdır), sonra quarto check. Tarayıcıda bu araçlar yok; aşağıdaki alıştırmalar notebook JSON'u üzerinde aynı işleri yapıyor.Restart and Run All'u otomatikleştirmek
Bir notebook'un temiz olup olmadığını, kod hücrelerini yeni ve boş bir ad alanında sırayla çalıştırarak denetleyebilirsin. Sihirli satırları atlamak gerekir; çünkü düz Python onları tanımaz:
hucreler = [
"%matplotlib inline\nimport math",
"yaricap = 3",
"alan = math.pi * yaricap ** 2",
"print(round(alan, 2), cevre)",
]
def bastan_calistir(kod_hucreleri):
ad_alani = {}
for i, kod in enumerate(kod_hucreleri):
temiz = "\n".join(s for s in kod.splitlines() if not s.lstrip().startswith(("%", "!")))
try:
exec(temiz, ad_alani)
except Exception as e:
return f"Hücre {i} başarısız: {type(e).__name__}: {e}"
return "Temiz: tüm hücreler sırayla çalıştı"
print(bastan_calistir(hucreler))
print(bastan_calistir(hucreler[:3]))
Parametreli notebook: papermill
papermill, bir notebook'u dışarıdan parametre vererek çalıştırır: "parameters" etiketli hücredeki değişkenleri ezer ve çıktılarıyla birlikte yeni bir notebook kaydeder. papermill rapor.ipynb cikti/ekim.ipynb -p ay 2026-10 gibi bir komutla aynı analizi her ay için üretebilirsin. Notebook artık bir "rapor şablonu" olur.
Çekirdek nedir, gerçekten?
Arayüz (tarayıcı ya da VS Code) ile çekirdek ayrı süreçlerdir ve mesajlaşma protokolüyle konuşur. Bu yüzden aynı arayüzle R, Julia ya da başka bir Python ortamının çekirdeğine bağlanabilirsin; jupyter kernelspec list kayıtlı çekirdekleri gösterir. "Hangi Python çalışıyor?" sorusunun notebook'taki cevabı bir hücrede import sys; print(sys.executable) çalıştırmaktır.