Debate

Python ile Klasör İzleme

Iniciado por CyberWolf · 09 jul 2026 11:21 · 17 Visitas · 0 Respuestas
Autor del tema #0
Python ile Klasör İzleme

Günümüzdeki otomasyon ve veri odaklı sistemlerde, belirli bir dizindeki değişiklikleri anlık olarak takip etmek, çoğu zaman kritik bir ihtiyaç haline geliyor. Bir dosya oluşturulduğunda otomatik bir işlem başlatmak, bir log dosyasının güncellendiğini anında fark edip analiz etmek, ya da konfigürasyon dosyalarında yapılan değişikliklere reaktif olmak... Tüm bunlar, sistemlerin daha dinamik ve verimli çalışmasını sağlayan senaryolar. Peki, Python gibi güçlü ve esnek bir dille bu izleme işlemini nasıl yaparız? İşte bugün bu konuyu enine boyuna inceleyeceğiz.

Şimdi düşünsenize, bir sunucuya yeni bir resim yüklendiğinde otomatik olarak boyutlandırma ve filigran ekleme yapmanız gerekiyor. Ya da bir uygulamanın çıktılarını yazdığı klasöre yeni bir rapor düştüğünde, bu raporu alıp başka bir sisteme aktarmanız lazım. Manuel olarak kontrol etmek, hele de bu işlemlerin yüzlerce kez tekrarlanması gerektiğinde, hem zaman kaybı hem de insan hatasına açık bir süreç. İşte tam da burada Python'ın klasör izleme yetenekleri devreye giriyor ve işleri sizin için otomatikleştiriyor.

Temel Yaklaşımlar: Manuel Yoklama (Polling) vs. Olay Tabanlı (Event-Driven) İzleme

Bir klasördeki değişiklikleri izlemenin iki temel yolu var aslında. Biri sürekli kontrol etmek, diğeri ise işletim sisteminin size "bir şeyler oldu" demesini beklemek.

Manuel Yoklama (Polling):
Bu yöntem, adından da anlaşılacağı gibi, belirli aralıklarla klasörü ziyaret edip içerisindeki dosyaların durumunu kontrol etmeye dayanır. Python'da bunu os modülü ile kolayca yapabiliriz. Diyelim ki bir klasördeki dosya sayısını veya son değişiklik tarihlerini takip etmek istiyorsunuz. os.listdir() ile klasörün içeriğini listeleyip, os.stat() ile her dosyanın metadata'sına erişebilirsiniz.

Bu yaklaşımın en büyük avantajı basitliğidir. Ek bir kütüphaneye ihtiyacınız olmaz, standart Python fonksiyonlarıyla işinizi görürsünüz. Ancak dezavantajları da bir o kadar önemlidir. Her şeyden önce, sürekli klasörü kontrol etmek demek, gereksiz yere sistem kaynaklarını tüketmek demektir. Özellikle büyük klasörlerde veya çok sık kontrol etmeniz gerektiğinde bu durum belirginleşir. Diyelim ki her saniye kontrol ediyorsunuz, ama değişiklikler sadece günde bir kez oluyor. Bu, 86.399 gereksiz kontrol anlamına gelir. Ayrıca, kontrol aralıkları arasında gerçekleşen bir değişikliği kaçırma veya geç fark etme riski de cabası. Gerçek zamanlıya yakın bir izleme için pek ideal değil, değil mi?

Şöyle basit bir örnekle ne demek istediğimi daha net anlatabilirim:

CODE
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
import os
import time

def check_folder_for_changes(folder_path, interval=5):
    print(f"'{folder_path}' klasörünü her {interval} saniyede bir kontrol ediyorum...")
    
    # Başlangıç durumu: Klasördeki dosyaların isimleri ve son değişiklik tarihleri
    previous_state = {}
    for filename in os.listdir(folder_path):
        filepath = os.path.join(folder_path, filename)
        if os.path.isfile(filepath):
            previous_state[filepath] = os.path.getmtime(filepath)

    while True:
        time.sleep(interval)
        current_state = {}
        current_files = set()

        for filename in os.listdir(folder_path):
            filepath = os.path.join(folder_path, filename)
            current_files.add(filepath)
            if os.path.isfile(filepath):
                current_state[filepath] = os.path.getmtime(filepath)
        
        # Yeni dosyaları bulma
        new_files = set(current_state.keys()) - set(previous_state.keys())
        for f in new_files:
            print(f"[YENİ] Dosya oluşturuldu: {os.path.basename(f)}")
        
        # Silinen dosyaları bulma
        deleted_files = set(previous_state.keys()) - set(current_state.keys())
        for f in deleted_files:
            print(f"[SİLİNDİ] Dosya silindi: {os.path.basename(f)}")

        # Değişen dosyaları bulma
        for f, mtime in current_state.items():
            if f in previous_state and previous_state[f] != mtime:
                print(f"[DEĞİŞTİ] Dosya güncellendi: {os.path.basename(f)}")
        
        previous_state = current_state
        #print("Klasör durumu güncellendi.") # Çok fazla çıktı olmaması için yorum satırı yaptım.

if [b]name[/b] == "[b]main[/b]":
    # İzlemek istediğiniz klasör yolunu buraya yazın
    # Örn: 'C:\\Users\\KullaniciAdi\\Desktop\\TestKlasoru' veya '/home/kullanici/test_klasoru'
    target_folder = "./test_klasoru" 
    
    # Eğer klasör yoksa oluştur
    if not os.path.exists(target_folder):
        os.makedirs(target_folder)
        print(f"'{target_folder}' klasörü oluşturuldu.")

    check_folder_for_changes(target_folder, interval=2)


Bu kod, belirlenen klasördeki dosyaların son değişiklik zamanlarını tutarak, her kontrol döngüsünde bu bilgiyi güncel durumla karşılaştırır. Yeni dosyaları, silinen dosyaları ve güncellenen dosyaları tespit edebilir. Ancak, gördüğünüz gibi, bu sürekli bir döngü ve dosya sistemine yapılan her os.listdir() ve os.stat() çağrısı bir maliyet. Küçük ölçekli, gecikmenin sorun olmadığı yerlerde iş görebilir belki... Ama daha fazlası için, daha "akıllı" bir şeye ihtiyacımız var.

Olay Tabanlı (Event-Driven) İzleme:
İşte modern ve verimli yaklaşım burada devreye giriyor. Olay tabanlı izleme, işletim sisteminin sunduğu dosya sistemi olay API'larını kullanarak çalışır. Linux'ta inotify, Windows'ta ReadDirectoryChangesW, macOS'ta ise FSEvents gibi mekanizmalar vardır. Bu API'lar, dosya sisteminde bir değişiklik olduğunda (dosya oluşturma, silme, taşıma, değiştirme vb.) işletim sisteminin bir bildirim göndermesini sağlar. Siz de bu bildirimleri dinlersiniz.

Bu yaklaşımın avantajları saymakla bitmez:
  • Gerçek Zamanlıya Yakın: Değişiklikler neredeyse anında algılanır.
  • Düşük Kaynak Tüketimi: Sürekli kontrol yapmak yerine, sadece bir olay olduğunda tetiklenirsiniz. Bu, CPU ve disk I/O kaynaklarını çok daha verimli kullanır.
  • Daha Kapsamlı Bilgi: Hangi tür olayın gerçekleştiği (oluşturuldu, silindi, taşındı, değiştirildi) hakkında bilgi alabilirsiniz.
Dezavantajı ise, bu işletim sistemi API'larının platforma özgü olmasıdır. Yani Linux için yazdığınız kod Windows'ta çalışmaz, macOS'ta da farklı bir yaklaşım gerekir. Neyse ki Python dünyasında bu sorunu çözen harika bir kütüphane var: watchdog.

Python'da Olay Tabanlı İzleme: Watchdog Kütüphanesi

watchdog, Python'da dosya sistemi olaylarını platformlar arası bir şekilde izlemek için tasarlanmış, güçlü ve kullanımı kolay bir kütüphanedir. Linux'taki inotify, Windows'taki ReadDirectoryChangesW ve macOS'taki FSEvents gibi yerel API'ları soyutlayarak size tek ve tutarlı bir arayüz sunar. Bu da demek oluyor ki, bir kere kod yazarsınız ve bu kod farklı işletim sistemlerinde sorunsuz çalışır.

Kurulumu:
watchdog'u kurmak oldukça basit. Python'ın paket yöneticisi pip ile tek bir komutla halledebilirsiniz:
CODE
12
pip install watchdog


Temel Bileşenler:
watchdog kütüphanesi, iki ana bileşen etrafında döner:
  • Observer (Gözlemci): Bu, izleme işlemini başlatan ve durduran ana nesnedir. Bir veya daha fazla dizini izlemek üzere yapılandırılır ve olay işleyicilerini (event handlers) kaydeder. Bir nevi orkestra şefi gibi düşünebilirsiniz.
  • FileSystemEventHandler (Dosya Sistemi Olay İşleyicisi): Bu, dosya sisteminde bir değişiklik olduğunda tetiklenen özel bir sınıftır. watchdog kütüphanesi, temel bir FileSystemEventHandler sınıfı sağlar ve siz bu sınıfı miras alarak kendi özel olay işleyicilerinizi yazarsınız. Bu sınıfta, dosya oluşturma (on_created), silme (on_deleted), taşıma (on_moved) ve değiştirme (on_modified) gibi olaylar için özel metotlar tanımlarsınız.

Basit Bir Watchdog Uygulaması:
Şimdi gelin, watchdog ile basit bir klasör izleyici nasıl yazılır, bir göz atalım. Bir klasördeki herhangi bir değişikliği (oluşturma, silme, değiştirme, taşıma) algılayıp ekrana yazdıran bir uygulama geliştirelim.

CODE
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import os

class MyHandler(FileSystemEventHandler):
    def on_created(self, event):
        if not event.is_directory:
            print(f"[OLUŞTURULDU] Dosya: {event.src_path}")
        else:
            print(f"[OLUŞTURULDU] Klasör: {event.src_path}")

    def on_deleted(self, event):
        if not event.is_directory:
            print(f"[SİLİNDİ] Dosya: {event.src_path}")
        else:
            print(f"[SİLİNDİ] Klasör: {event.src_path}")

    def on_modified(self, event):
        if not event.is_directory:
            print(f"[DEĞİŞTİRİLDİ] Dosya: {event.src_path}")
        else:
            print(f"[DEĞİŞTİRİLDİ] Klasör: {event.src_path}")

    def on_moved(self, event):
        if not event.is_directory:
            print(f"[TAŞINDI/YENİDEN ADLANDIRILDI] Dosya: {event.src_path} -> {event.dest_path}")
        else:
            print(f"[TAŞINDI/YENİDEN ADLANDIRILDI] Klasör: {event.src_path} -> {event.dest_path}")

if [b]name[/b] == "[b]main[/b]":
    # İzlemek istediğiniz klasör yolunu buraya yazın
    # Örn: 'C:\\Users\\KullaniciAdi\\Desktop\\TestKlasoru' veya '/home/kullanici/test_klasoru'
    path = "./test_klasoru"

    # Eğer klasör yoksa oluştur
    if not os.path.exists(path):
        os.makedirs(path)
        print(f"'{path}' klasörü oluşturuldu.")

    event_handler = MyHandler()
    observer = Observer()
    
    # Klasörü izlemeye başla. recursive=True alt klasörleri de izler.
    observer.schedule(event_handler, path, recursive=True)
    
    observer.start()
    print(f"'{path}' klasörü izleniyor. Çıkmak için Ctrl+C'ye basın.")
    
    try:
        while True:
            time.sleep(1) # Observer'ın arka planda çalışmasını sağlar
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
    print("Klasör izleme durduruldu.")


Bu kod parçası ne yapıyor?
  • Öncelikle MyHandler adında, FileSystemEventHandler sınıfından miras alan kendi olay işleyicimizi tanımlıyoruz.
  • Bu sınıfta, on_created, on_deleted, on_modified ve on_moved metotlarını override ediyoruz. Her metot, ilgili olay tetiklendiğinde çalışacak kodu içeriyor. event nesnesi, olayın türü, kaynak yolu (src_path) ve hedef yolu (dest_path - sadece taşıma olaylarında) gibi bilgileri barındırır.
  • main bloğunda, izlenecek klasör yolunu belirtiyoruz.
  • Bir MyHandler örneği oluşturup, ardından bir Observer nesnesi yaratıyoruz.
  • observer.schedule() metodu ile hangi olay işleyiciyi hangi klasörde ve özyinelemeli (alt klasörleri de dahil et) olarak izleyeceğimizi belirtiyoruz. recursive=True çok önemli, aksi takdirde sadece belirtilen dizinin kendisindeki olayları dinler, alt dizinleri görmez.
  • observer.start() ile izleme işlemini başlattıktan sonra, ana iş parçacığının bitmemesi için bir sonsuz döngü (while True) içinde time.sleep(1) ile bekliyoruz. Bu, observer'ın kendi iş parçacığında arka planda çalışmaya devam etmesini sağlar.
  • Kullanıcı Ctrl+C ile programı sonlandırmak istediğinde, KeyboardInterrupt yakalanır, observer.stop() ile izleme durdurulur ve observer.join() ile observer iş parçacığının güvenli bir şekilde sonlanması beklenir.

Bu kod ile test_klasoru içine dosya ekleyin, silin, adını değiştirin veya içeriğini güncelleyin; anında konsolda çıktıyı göreceksiniz. Gerçekten de çok etkili bir yöntem, değil mi?

Gelişmiş Kullanım Senaryoları:

  • Belirli Dosya Türlerini Filtreleme: Bazen sadece belirli uzantıya sahip dosyalarla ilgilenirsiniz. Örneğin, sadece .log veya .txt uzantılı dosyaları izlemek isteyebilirsiniz. watchdog'un PatternMatchingEventHandler sınıfını kullanarak bunu kolayca yapabilirsiniz. Bu sınıf, belirli desenlere uyan dosyaları dahil etme (patterns) veya hariç tutma (ignore_patterns) yeteneği sunar.
    CODE
    1234567891011
        from watchdog.events import PatternMatchingEventHandler
    
        class LogFileHandler(PatternMatchingEventHandler):
            def [b]init[/b](self):
                super().[b]init[/b](patterns=["*.log"], ignore_directories=True)
    
            def on_created(self, event):
                print(f"Yeni log dosyası oluşturuldu: {event.src_path}")
            
            # Diğer olayları da burada tanımlayabilirsiniz
        

    Bu şekilde sadece .log uzantılı dosyaların olayları tetiklenir.

  • Debouncing ve Throttling (Olay Birleştirme ve Sıklık Sınırlama): Özellikle dosya kaydetme işlemleri sırasında bir dosya üzerinde birden fazla on_modified olayı tetiklenebilir. Örneğin, bir metin editörü dosyayı kaydederken birkaç milisaniye içinde arka arkaya birden fazla değişiklik olayı gönderebilir. Eğer her olayda ağır bir işlem yapıyorsanız, bu performans sorunlarına yol açabilir. watchdog doğrudan bir debouncing mekanizması sunmasa da, kendi olay işleyicinizde bir zamanlayıcı (threading.Timer) veya özel bir kütüphane (debounce gibi) kullanarak ardışık olayları birleştirebilir veya belirli bir süre içinde yalnızca bir kez işlem yapmasını sağlayabilirsiniz. Bu, özellikle kaynak yoğun işlemlerde çok önemlidir.

  • Birden Fazla Dizini İzleme: Tek bir Observer nesnesi kullanarak birden fazla dizini aynı anda izleyebilirsiniz. Her izlenecek dizin ve olay işleyici çifti için observer.schedule() metodunu çağırmanız yeterlidir.
    CODE
    12345
        # ...
        observer.schedule(handler_for_dir1, '/path/to/dir1', recursive=True)
        observer.schedule(handler_for_dir2, '/path/to/dir2', recursive=False)
        # ...
        

    Her dizin için farklı olay işleyicileri bile atayabilirsiniz, bu da size inanılmaz bir esneklik sunar.

Pratik Uygulama Alanları ve İpuçları

Klasör izleme, düşündüğünüzden çok daha fazla yerde işinize yarayabilir. İşte bazı örnekler:

  • Log Dosyalarını İzleme ve Anlık İşleme: Bir uygulamanın log dosyalarını izleyerek, belirli hata mesajlarını veya önemli olayları anında tespit edip bildirim gönderebilir, hatta otomatik düzeltme mekanizmaları tetikleyebilirsiniz.
  • Otomatik Dosya İşleme İş Akışları: Bir klasöre yeni bir belge yüklendiğinde (PDF, resim, video), bu dosyayı otomatik olarak işleyip (sıkıştırma, format dönüştürme, OCR, virüs taraması) başka bir yere taşıyabilirsiniz. Örneğin, bir e-ticaret sitesine yüklenen ürün görsellerini otomatik olarak farklı boyutlarda önbellek kopyalarını oluşturmak gibi.
  • Konfigürasyon Dosyası İzleme: Uygulamanızın kullandığı bir konfigürasyon dosyasında değişiklik yapıldığında, uygulamayı otomatik olarak yeniden başlatabilir veya ayarları dinamik olarak güncelleyebilirsiniz. Bu, özellikle sürekli çalışan servisler için harika bir yaklaşımdır.
  • Veri Senkronizasyonu ve Yedekleme: Yerel bir klasördeki değişiklikleri uzaktaki bir sunucuya (bulut depolama, FTP) anında senkronize etmek veya yedeklemek için kullanabilirsiniz.

Performans ve Kaynak Yönetimi Hakkında İpuçları:
  • Sadece İhtiyacınız Olan Dizinleri İzleyin: Gereksiz yere tüm bir diski veya çok sayıda büyük klasörü izlemekten kaçının. Ne kadar az dizin izlerseniz, o kadar az kaynak tüketirsiniz.
  • Olay İşleyicilerinde Bloklama İşlemlerinden Kaçının: on_created veya on_modified gibi metotların içinde uzun süreli veya bloklama yapan (örneğin, ağ çağrısı, veritabanı işlemi, büyük dosya işleme) işlemler yapmaktan kaçının. Bu, diğer olayların işlenmesini geciktirebilir. Eğer böyle bir işlem yapmanız gerekiyorsa, bunu ayrı bir iş parçacığında (threading) veya asenkron bir görevde (asyncio) çalıştırmayı düşünün.
  • Hata Yönetimi: Olay işleyicilerinizde hata yakalama mekanizmaları (try-except) kullanın. Bir hata, tüm izleme sürecini durdurabilir. Hataları loglayın ve gerektiğinde programın sağlıklı bir şekilde çalışmaya devam etmesini sağlayın.

Alternatifler ve Diğer Kütüphaneler (Kısaca)

watchdog çoğu senaryo için harika bir seçim olsa da, bazen platforma özgü daha düşük seviyeli kütüphaneleri kullanmak isteyebilirsiniz. Örneğin:
  • pyinotify (Linux): Sadece Linux sistemleri için tasarlanmış, inotify kernel arayüzüne doğrudan erişim sağlayan bir kütüphanedir. Eğer sadece Linux üzerinde çalışacak bir çözüm geliştiriyorsanız ve watchdog'un soyutlama katmanına ihtiyacınız yoksa, daha düşük seviyeli kontrol sunabilir.
  • win32file (Windows - pywin32 paketi içinde): pywin32 paketi, Windows API'larına Python'dan erişim sağlar. win32file.ReadDirectoryChangesW fonksiyonunu doğrudan kullanarak Windows'a özgü dosya sistemi değişikliklerini izleyebilirsiniz. Ancak bu, watchdog'a göre çok daha fazla manuel kodlama gerektirir ve platform bağımsız değildir.
Genel olarak, platform bağımsızlık ve kullanım kolaylığı arıyorsanız, watchdog ilk tercihiniz olmalı.

Sonuç ve Tartışma Başlatma

Gördüğünüz gibi, Python ile klasör izleme, manuel yoklama gibi basit ama verimsiz yöntemlerden, watchdog gibi gelişmiş ve olay tabanlı çözümlere kadar geniş bir yelpazeyi kapsıyor. İhtiyaçlarınıza göre doğru aracı seçmek, uygulamanızın performansını ve güvenilirliğini doğrudan etkileyecektir. Özellikle otomasyon, veri işleme ve gerçek zamanlı sistemlerde watchdog gibi kütüphaneler hayat kurtarıcı olabilir.

Peki, sizin bu konudaki tecrübeleriniz neler? Daha önce Python ile klasör izleme yaptınız mı? Hangi kütüphaneleri kullandınız, ne gibi zorluklarla karşılaştınız veya ne gibi yaratıcı çözümler ürettiniz? Belki de benim bahsetmediğim farklı bir yaklaşımınız vardır, kim bilir... Yorumlarınızı ve deneyimlerinizi merakla bekliyorum, gelin bu konuyu hep birlikte daha da derinleştirelim!

Debes haber iniciado sesión para responder.

0 citas seleccionadas