os Modülü¶
Bildiğiniz gibi, işletim sistemlerinin çalışma mantığı birbirinden farklıdır.
Örneğin Windows ve GNU/Linux işletim sistemleri aynı işi birbirlerinden farklı
şekillerde yaparlar. Mesela Windows’ta bir dizin içinde hangi klasör ve
dosyaların olduğunu öğrenmek için dir
komutunu kullanırız. GNU/Linux’ta ise
aynı işlev için ls
adlı bir komut vardır.
Aynı şekilde, iki işletim sistemi arasında dizin ayraçları konusunda da farklılık bulunur. Windows’ta dizinleri birbirinden ayırmak için ters taksim (\) işareti kullanılırken, GNU/Linux’ta aynı iş için düz taksim (/) işareti kullanılır.
Not
Düz taksim işaretini Windows da kabul eder, ancak Windows’un doğal dizin ayracı ters taksimdir.
İşte biz hem Windows’ta, hem de GNU/Linux’ta çalışacak bir program yazmak
istediğimizde bu farklılıkları göz önünde bulundurmamız ve farklı durumların
her biri için ayrı kodlar yazmamız gerekirken, os
modülü bizi bu zahmetten
kurtarır ve bize ortak bir arayüz üzerinden farklı işletim sistemleri ile
tutarlı bir şekilde iletişim kurabilmemizi sağlayacak pek çok fonksiyon ve
nitelik sunar.
Bu nitelik ve fonksiyonların neler olduğunu dir(os)
komutuyla
görebileceğinizi biliyorsunuz.
Bu bölümde, os
modülünün sunduğu bu fonksiyon ve niteliklerin en
önemlilerini ve en yaygın kullanılanlarını olabildiğince ayrıntılı bir şekilde
ele almaya çalışacağız.
Not
Burada os
modülünü import os
komutuyla içe aktarmış olduğunuz
varsayılmaktadır.
os.name¶
os
modülünün, önceki derslerde şöyle bir değinip geçtiğimiz name niteliği,
kullanıcılarımızın, yazdığımız kodları hangi işletim sisteminde çalıştırdığı
konusunda bize bilgi verir.
Bu niteliği şöyle kullanıyoruz:
>>> os.name
Eğer kodlarımız Windows işletim sistemi üzerinde çalıştırılmışsa buradan şu çıktıyı alırız:
'nt'
MacOS ve GNU/Linux işletim sistemleri ise bu komuta şu cevabı verir:
'posix'
Dolayısıyla os.name
niteliğini kullanarak farklı işletim sistemlerinde
farklı çalışan programlar yazabiliriz.
os.sep¶
os
modülünün sep niteliği, kodlarımızın çalıştığı işletim sisteminin dizin
ayracının ne olduğunu bize gösterir.
Eğer bu niteliği Windows işletim sistemi üzerinde kullanırsak şu çıktıyı alırız:
>>> os.sep
'\\'
MacOS ve GNU/Linux işletim sistemleri ise bu komuta şu cevabı verir:
>>> os.sep
'/'
Peki bu nitelik ne işe yarar?
Bu niteliği kullanarak, farklı işletim sistemlerine özgü dizin yolları oluşturabilirsiniz. Mesela:
>>> liste = ['aylar', 'mayıs', 'test']
>>> os.sep.join(liste)
Burada karakter dizilerinin join()
metodunu os.sep
ile birlikte
kullandığımıza dikkat edin.
Bu komutu Windows’ta verdiğinizde şu çıktıyı alırsınız:
'aylar\\mayıs\\test'
Aynı komutu GNU/Linux’ta verdiğinizde ise şu çıktıyı:
'aylar/mayıs/test'
Yani yukarıdaki komutu Windows’ta verdiğinizde Python şu komutu almış gibi davranır:
>>> liste = ['aylar', 'mayıs', 'test']
>>> '\\'.join(liste)
GNU/Linux’ta ise şu komutu:
>>> liste = ['aylar', 'mayıs', 'test']
>>> '/'.join(liste)
Böylece yazdığınız programlarda hangi işletim sisteminin hangi dizin ayracını kullandığını düşünmenize gerek kalmaz; bunu sizin yerinize Python düşünür…
os.getcwd()¶
os
modülünün getcwd()
fonksiyonu bize o anda içinde bulunduğumuz dizinin
adını verir:
>>> os.getcwd()
'/home/istihza/Desktop' #GNU/Linux
veya:
>>> os.getcwd()
'C:\\Documents and Settings\\fozgul' #Windows
os.chdir()¶
os
modülünün chdir()
fonksiyonu bize bir dizinden başka bir dizine geçme
imkanı verir.
Mesela GNU/Linux’ta, o anda bulunduğumuz dizinden /usr/bin adlı dizine geçmek için şu komutu kullanabiliriz:
>>> os.chdir('/usr/bin/')
veya Windows’ta C:\Documents and Settings\fozgul\Desktop adlı dizine geçmek için şunu:
>>> os.chdir('C:\\Documents and Settings\\fozgul\\Desktop')
Gördüğünüz gibi, gitmek istediğimiz dizin adını os.chdir()
fonksiyonuna
parametre olarak vermemiz yeterli oluyor.
os.listdir()¶
os
modülünün listdir()
fonksiyonu, bize bir dizin içindeki dosya ve
klasörleri listeleme imkanı verir. listdir()
, os
modülünün en kullanışlı
fonksiyonlarından biridir.
Mesela o anda içinde bulunduğumuz dizindeki dosya ve klasörleri listelemek istersek bu fonksiyonu şöyle kullanabiliriz:
>>> mevcut_dizin = os.getcwd()
>>> os.listdir(mevcut_dizin)
Eğer farklı bir dizinin içeriğini listelemek istersek, parametre olarak o dizinin adını yazmamız yeterli olacaktır:
>>> os.listdir('/var/www')
Gördüğünüz gibi, os.listdir()
komutunun çıktısı liste türünde bir veri
tipidir. Dolayısıyla listelerle yapabildiğiniz her şeyi bununla da
yababilirsiniz. Mesela bu liste üzerinde bir döngü kurabilirsiniz:
>>> for i in os.listdir(os.getcwd()):
... print(i)
Ya da bir dizin içindeki, belli bir uzantıya sahip dosyaları süzebilirsiniz:
>>> for i in os.listdir(os.getcwd()):
... if i.endswith('.doc'):
... print(i)
Bu kodlar bize, adı .doc ile biten bütün dosyaları listeleyecektir.
Bu arada karakter dizilerinin endswith()
adlı metodunu hatırlıyorsunuz,
değil mi?
os.curdir¶
Çoğu işletim sisteminde mevcut dizini göstermek için ‘.’ adlı karakter dizisi kullanılır. Örneğin:
>>> os.listdir(os.getcwd())
gibi bir komut yerine şu komutu da kullanabilirsiniz:
>>> os.listdir('.')
listdir()
fonksiyonuna parametre olarak verdiğimiz ‘.’ karakter dizisi o
anda içinde bulunduğumuz dizini temsil eder.
Eğer bu karakter dizisini elle yazmak istemiyorsanız os
modülü içindeki
curdir adlı nitelikten de yararlanabilirsiniz:
>>> os.listdir(os.curdir)
Bu arada os.getcwd()
ile os.curdir’i birbirine karıştırmamalısınız. Bu
ikisi aynı şey değildir. os.getcwd()
çıktı olarak o anda içinde bulunduğumuz
dizinin adını verir. os.curdir ise, bir işletim sisteminde, o anda içinde
bulunulan dizini temsil eden karakter dizisi ne ise onun değerini barındırır. Bu
değer çoğu işletim sisteminde ‘.’ adlı karakter dizisidir.
os.pardir¶
Tıpkı ‘.’ karakter dizisi gibi, çoğu işletim sisteminde bir üst dizini göstermek için ‘..’ adlı karakter dizisi kullanılır. Örneğin:
>>> os.listdir('..')
komutu, o anda içinde bulunduğunuz dizindeki değil, bir üst dizindeki dosya ve dizin adlarını listeleyecektir. Yine tıpkı os.curdir niteliğinde olduğu gibi, eğer bu karakter dizisini kendiniz elle yazmak istemezseniz, bu karakter dizisini içinde barındıran os.pardir adlı bir nitelikten yararlanabilirsiniz:
>>> os.listdir(os.pardir)
Bu komut, os.listdir('..')
ile aynı çıktıyı verir.
os.startfile()¶
Uyarı
Bu fonksiyon yalnızca Windows’ta çalışır. GNU/Linux işletim sistemlerinde bu fonksiyon tanımlı değildir.
os
modülü içindeki startfile()
adlı fonksiyonun görevi bilgisayarımızda
bulunan herhangi bir dosyayı, ilişkilendirilmiş olduğu programla açmaktır.
Hemen bir örnek verelim.
O anda içinde bulunduğumuz dizinde deneme.txt adlı bir dosya olduğunu varsayalım. Şimdi de şu komutu verelim:
>>> os.startfile('deneme.txt')
İşletim sisteminiz .txt uzantılı dosyaları hangi programla ilişkilendirmişse,
startfile()
fonksiyonu deneme.txt adlı dosyayı o programla açacaktır.
Windows’ta .txt dosyaları genellikle Notepad programıyla ilişkilendirildiği
için yukarıdaki komutu verdiğinizde muhtemelen deneme.txt dosyasının içeriği
Notepad programı aracılığıyla görüntülenecektir.
Aynı şekilde, o anda bulunduğuz dizin içinde deneme.docx adlı bir dosyanın olduğunu varsayalım ve şu komutu verelim:
>>> os.startfile('deneme.docx')
Bu komut da deneme.docx dosyasının Microsoft Word adlı yazılımla açılmasını sağlayacaktır.
Eğer startfile()
fonksiyonuna parametre olarak bir dosya değil de dizin adı
verecek olursanız, o dizin Windows Explorer ile açılır. Mesela içinde
bulunduğumuz dizini Windows Explorer ile açalım:
>>> os.startfile(os.curdir)
Bunun yerine şu komutu kullanabileceğinizi de biliyorsunuz:
>>> os.startfile('.')
veya:
>>> os.startfile(os.getcwd())
Bu üç komut da aynı işlevi yerine getirir.
Peki bir üst dizini açmak istersek ne yapacağız?
Dikkatlice bakın:
>>> os.startfile(os.pardir)
veya:
>>> os.startfile('..')
Her iki komut da Windows Explorer yardımıyla bir üst dizinin görüntülenmesini sağlayacaktır.
Elbette startfile()
fonksiyonuna parametre olarak belirli bir dizinin adını
da verebilirsiniz:
>>> os.startfile(r"C:\Documents and Settings\fozgul")
os.startfile()
oldukça faydalı bir fonksiyondur. Hatta bu fonksiyonu sadece
dosyaları açmak için değil, internet sayfalarını açmak için dahi
kullanabilirsiniz:
>>> os.startfile('www.istihza.com')
Ancak bu komutun yalnızca Windows’ta çalışacağını unutmayın. O yüzden bunun
yerine, daha önce öğrendiğimiz webbrowser
modülünü kullanmak daha doğru
olacaktır.
os.mkdir()¶
os
modülünün mkdir()
fonksiyonu yeni dizinler oluşturabilmemizi sağlar.
Örneğin:
>>> os.mkdir('yenidizin')
Bu komut, o anda içinde bulunduğumuz dizin içinde ‘yenidizin’ adlı bir dizin oluşturacaktır.
Elbette eğer dizini o anda içinde bulunduğunuz dizin içinde değil de farklı bir konumda oluşturmak isterseniz, o konumun açık adresini belirtebilirsiniz:
>>> os.mkdir('/home/istihza/Desktop/yenidizin')
veya:
>>> os.mkdir(r'C:\Documents and Settings\fozgul\yenidizin')
Eğer oluşturmaya çalıştığınız dizin zaten varsa os.mkdir()
hata verecektir:
>>> os.mkdir(r'C:\Documents and Settings\fozgul\yenidizin')
FileExistsError: [WinError 183] Halen varolan bir
dosya oluşturulamaz: 'yenidizin'
os.makedirs()¶
os.makedirs()
fonksiyonu biraz önce öğrendiğimiz os.mkdir()
fonksiyonuna
çok benzese de aralarında önemli farklar bulunur.
Biraz önce os.mkdir()
fonksiyonunu anlatırken şöyle bir örnek vermiştik:
>>> os.mkdir(r'C:\Documents and Settings\fozgul\yenidizin')
Bu komutun çalışabilmesi için, bilgisayarımızda halihazırda C:Documents and Settingsfozgul` yolunun varolması gerekir. Eğer bu yolu oluşturan dizinlerden herhangi biri mevcut değilse, ``mkdir()` fonksiyonu yenidizin adlı dizini oluşturamaz. Bu fonksiyonun çalışabilmesi için, varolmayan bütün dizinleri tek tek oluşturmanız gerekir.
os.makedirs()
ise os.mkdir()
fonksiyonunun aksine, varolmayan üst ve alt
dizinleri de oluşturma yeteneğine sahiptir. Örneğin:
>>> os.makedirs('/home/istihza/Desktop/aylar/mayıs/ödeme/')
Bu komut sırasıyla aylar, mayıs ve ödeme adlı dizinleri iç içe
oluşturacaktır. Yani os.makedirs()
komutunun ödeme adlı dizini oluşturması
için aylar ve mayıs adlı dizinlerin önceden varolması zorunlu değildir. Bu
dizinler varolsa da olmasa da os.makedirs()
komutu ödeme dizinini
oluşturabilir. Ama os.mkdir()
fonksiyonu böyle değildir. Eğer os.mkdir()
fonksiyonuyla ödeme dizinini oluşturmak isterseniz, öncelikle aylar ve
mayıs adlı dizinleri oluşturmanız gerekir.
os.rename()¶
os
modülünün rename()
adlı fonksiyonunu kullanarak dizinlerin adlarını
değiştirebiliriz. Bu fonksiyon iki parametre alır:
>>> os.rename('dizinin_şimdiki_adı', 'dizinin_yeni_adı')
Mesela mevcut çalışma dizininde ‘deneme’ adlı bir dizin varsa, bu dizinin adını ‘test’ olarak değiştirmek için şu komutu verebiliriz:
>>> os.rename('deneme', 'test')
Eğer zaten ‘test’ adlı bir dizin varsa (ve içi boşsa), yukarıdaki komut GNU/Linux’ta ‘test’ adlı dizinin üzerine yazacak, Windows’ta ise hata verecektir.
os.replace()¶
os
modülünün replace()
fonksiyonu biraz önce öğrendiğimiz rename()
fonksiyonu gibi çalışır:
>>> os.replace('deneme', 'test')
Bu komut, tıpkı rename()
fonksiyonunda olduğu gibi, deneme adlı dizinin
adını test olarak değiştirecektir.
Eğer test adlı bir dizin zaten varsa, replace()
fonksiyonu, hem Windows’ta
hem de GNU/Linux’ta, varolan bu test dizininin üzerine yazmaya çalışır.
GNU/Linux’ta çoğu durumda bunu başarır, ancak Windows’ta yine de çeşitli izin
hataları ile karşılaşabilirsiniz.
os.remove()¶
os
modülünün remove()
adlı fonksiyonu, bilgisayarımızdaki dosyaları
silmemizi sağlar:
>>> os.remove('dosya_adı')
Yalnız bu komutu çok dikkatli kullanmalısınız. Çünkü bu komut, silme işleminden önce herhangi bir soru sormadan, dosyayı doğrudan siler.
os.rmdir()¶
os
modülünün rmdir()
fonksiyonu, içi boş bir dizini silmek için
kullanılır:
>>> os.rmdir('dizin_adı')
Eğer silmeye çalıştığınız dizin içinde herhangi bir başka dizin veya dosya varsa bu fonksiyon hata verecektir.
Mesela şöyle bir dizin yapısı düşünelim:
|___ anadizin
|___ dizin1
|___ dizin2
|___ dizin3
|___ dizin4
Bu arada, bu dizin yapısını kolayca oluşturmak için ne yapmanız gerektiğini biliyorsunuz:
>>> os.makedirs('anadizin/dizin1/dizin2/dizin3/dizin4')
Anadizin altındayken şu komutlar hata verecektir:
>>> os.rmdir('anadizin')
>>> os.rmdir(r'anadizin/dizin1')
>>> os.rmdir(r'anadizin/dizin1/dizin2/dizin3')
Çünkü bu dizinlerinin hiçbirinin içi boş değil; her birinin içinde birer dizin var. Ama şu komut başarılı olacaktır:
>>> os.rmdir(r'anadizin/dizin1/dizin2/dizin3/dizin4')
Bu şekilde yukarı doğru ilerleyerek sırayla bütün dizinleri silebilirsiniz:
>>> os.rmdir(r'anadizin/dizin1/dizin2/dizin3/')
>>> os.rmdir(r'anadizin/dizin1/dizin2/')
>>> os.rmdir(r'anadizin/dizin1')
>>> os.rmdir(r'anadizin/')
os.removedirs()¶
os
modülünün removedirs()
fonksiyonu, içi boş dizin yollarını silmemizi
sağlar. Peki bu ne demek?
Diyelim ki elimizde şöyle bir dizin yapısı var:
|___ anadizin
|___ dizin1
|___ dizin2
|___ dizin3
|___ dizin4
Anadizin altından şu komutu verdiğimizde:
>>> os.removedirs('anadizin/dizin1/dizin2/dizin3/dizin4')
Eğer bütün dizinlerin içi boşsa, anadizin’den dizin4’e kadar olan bütün dizinler (anadizin ve dizin4 dahil) silinecektir.
os.stat()¶
os
modülünün stat()
fonksiyonu dosyalar hakkında bilgi almamızı sağlar.
Bu fonksiyonu kullanarak bir dosyanın boyutunu, oluşturulma tarihini,
değiştirilme tarihini ve erişilme tarihini sorgulayabiliriz.
stat()
fonksiyonunu şöyle kullanıyoruz:
>>> dosya = os.stat('dosya_adı')
>>> dosya
Buradan şuna benzer bir çıktı alırız:
os.stat_result(st_mode=33279, st_ino=17732923532961356,
st_dev=1745874298, st_nlink=1, st_uid=0, st_gid=0,
st_size=495616, st_atime=1416488851, st_mtime=1415275662,
st_ctime=1415275658)
Bu, kendi içinde birtakım nitelikler barındıran özel bir veri tipidir. Bu veri
tipinin barındırdığı nitelikleri görmek için, her zaman olduğu gibi dir()
fonksiyonundan yararlanabilirsiniz:
dir(dosya)
Burada özellikle işimize yarayacak olan nitelikler şunlardır:
- st_atime:
dosyaya en son erişilme tarihi
- st_ctime:
dosyanın oluşturulma tarihi (Windows’ta)
- st_mtime:
dosyanın son değiştirilme tarihi
- st_size:
dosyanın boyutu
Mesela bir dosyanın boyutunu öğrenmek için st_size niteliğini şu şekilde kullanabiliriz:
>>> dosya = os.stat('dosya_adı')
>>> dosya.st_size
Bu fonksiyon bize ‘bayt’ cinsinden bir çıktı verir. Bunu kilobayta çevirmek için, bu değeri 1024’e bölebilirsiniz:
>>> dosya.st_size / 1024
os
modülünün stat()
fonksiyonunu kullanarak bir dosyanın oluşturulma,
erişilme ve değiştirilme tarihlerini de elde edebilirsiniz:
>>> dosya = os.stat('dosya_adı')
>>> dosya.st_ctime #oluşturulma tarihi
>>> dosya.st_atime #erişilme tarihi
>>> dosya.st_mtime #değiştirme tarihi
Uyarı
GNU/Linux’ta bir dosyanın ne zaman oluşturulduğunu öğrenmek mümkün
değildir. Dolayısıyla dosya.st_ctime
komutu yalnızca Windows’ta bir dosyanın
oluşturulma tarihi verir. Bu komutu GNU/Linux’ta verdiğimizde elde edeceğimiz
şey dosyanın son değiştirilme tarihidir.
Bu arada, yukarıdaki komutların çıktısı size anlamsız gelmiş olabilir. Birazdan,
datetime
adlı bir modülü öğrendiğimizde bu anlamsız görünen sayıları anlamlı
tarih bilgilerine nasıl dönüştüreceğimizi de anlatacağız.
os.system()¶
os
modülünün system()
fonksiyonu Python içinden sistem komutlarını veya
başka programları çalıştırabilmemizi sağlar. Mesela:
>>> os.system('notepad.exe')
os.urandom()¶
os
modülünün urandom()
fonksiyonu rastgele bayt dizileri elde etmek için
kullanılabilir:
>>> os.urandom(12)
Bu komut, 12 bayttan oluşan rastgele bir dizi oluşturur. Buradan elde ettiğiniz rastgele değeri kriptografik çalışmalarda veya rastgele parola üretme işlemlerinde kullanabilirsiniz.
os.walk()¶
Hatırlarsanız önceki sayfalarda os
modülü içindeki listdir()
adlı bir
fonksiyondan söz etmiştik. Bu fonksiyon, bir dizinin içeriğini listeleme imkanı
veriyordu bize. Mesela o anda içinde bulunduğumuz dizinde hangi dosya ve
alt dizinlerin olduğunu öğrenmek için şöyle bir komut kullanabiliyorduk:
>>> os.listdir('.')
['build.py', 'gtk', 'kitap', 'make.bat', 'Makefile',
'meta_conf.py', 'py2', 'py3', 'theme', 'tk2', '__pycache__']
Gördüğünüz gibi bu fonksiyon yalnızca kendisine parametre olarak verilen dizinin
içeriğini listeliyor. Örneğin yukarıdaki çıktıda görünen gtk, kitap,
py2, py3, theme, tk2 ve __pycache__ birer dizin. Ama listdir()
fonksiyonu bu dizinlerin de içine girip buradaki içeriği listelemeye çalışmıyor.
Eğer biz mesela theme dizininin içeriğini de listelemek istersek bunu açıkça
belirtmemiz gerekir:
>>> os.listdir('theme')
['layout.html', 'localtoc.html', 'pydoctheme',
'sidebar.html', 'static']
Veya theme dizini içindeki static adlı dizine de erişmek istersek bunu da şu şekilde açık açık ifade etmemiz gerekir:
>>> os.listdir('theme/static')
['basic.css', 'copybutton.js', 'py.png', 'sidebar.js']
Peki ya biz o anda içinde bulunduğumuz dizinden itibaren içe doğru bütün dizinleri otomatik olarak taramak istersek ne yapacağız?
Bunun için listdir()
fonksiyonunu kullanarak özyinelemeli (recursive) bir
fonksiyon yazabilirsiniz:
import os
def tara(dizin):
başlangıç = os.getcwd()
dosyalar = []
os.chdir(dizin)
for öğe in os.listdir(os.curdir):
if not os.path.isdir(öğe):
dosyalar.append(öğe)
else:
dosyalar.extend(tara(öğe))
os.chdir(başlangıç)
return dosyalar
Not
Bu kodlarda henüz öğrenmediğimiz tek şey os.path.isdir()
fonksiyonu. Bu fonksiyon, kendisine parametre olarak verilen bir değerin
dizin olup olmadığını tespit etmemizi sağlıyor.
Yukarıdaki kodlarda öncelikle o anda içinde bulunduğumuz dizinin konumunu başlangıç adlı bir değişkene atıyoruz. Çünkü daha sonra buraya dönmemiz gerekecek:
başlangıç = os.getcwd()
Ardından dosyalar adlı bir liste oluşturuyoruz:
dosyalar = []
Bu liste, dizinler içindeki bütün dosyaları içinde barındıracak.
Daha sonra, tara()
fonksiyonuna parametre olarak verilen dizin adlı
dizinin içine giriyoruz:
os.chdir(dizin)
Bu dizinin içine girdikten sonra, mevcut dizin içindeki bütün öğeleri
listdir()
fonksiyonu ile tek tek tarıyoruz:
for öğe in os.listdir(os.curdir):
...
Eğer tarama sırasında karşılaştığımız öğe bir dizin değil ise:
if not os.path.isdir(öğe):
...
Bu öğeyi, doğrudan en başta tanımladığımız dosyalar adlı listeye gönderiyoruz:
dosyalar.append(öğe)
Ama eğer tarama sırasında karşılaştığımız öğe bir dizin ise:
else:
...
tara()
fonksiyonunun en başına dönüp, tanımladığımız bütün işlemleri bu
dizin üzerine özyinelemeli olarak uyguluyoruz ve elde ettiğimiz öğeleri
dosyalar
adlı listeye extend()
metodu ile işliyoruz:
dosyalar.extend(tara(öğe))
Burada neden append()
değil de extend()
kullandığımızı anlamak için,
yukarıdaki kodu bir de append()
ile yazıp elde ettiğiniz çıktıyı
değerlendirebilirsiniz.
for
döngüsünden çıktıktan sonra da tekrar en baştaki konuma dönebilmek için
aşağıdaki komutu çalıştırıyoruz:
os.chdir(başlangıç)
Eğer bu şekilde başa dönmezsek, dizin yapısı içindeki ilk alt dizine girildikten
sonra programımız o konumda takılı kalacağı için öteki üst dizinlerin içini
tarayamaz. Bunun ne demek olduğunu anlamak için kodları bir de
os.chdir(başlangıç)
kodu olmadan çalıştırmayı deneyebilirsiniz.
Yukarıdaki yöntem doğru olsa da, Python’da bir dizini en dibe kadar taramanın en
iyi yolu değildir. Python bize bu iş için özel bir fonksiyon sunar. İşte, bu
bölümde ele alacağımız bu fonksiyonun adı walk()
.
Walk kelimesi İngilizcede ‘yürümek’ anlamına gelir. walk()
fonksiyonu da,
kelimenin bu anlamına uygun olarak, dizinler içinde ‘yürünmesini’ sağlar. Gelin
bunu biraz açıklayalım.
Şöyle bir durum düşünün: Sabit diskinizde, bir dizin içinde pek çok alt dizine dağılmış bir sürü dosya var. Yani şunun gibi:
+anadizin
|dosya.txt
|dosya.doc
|dosya.xls
|dosya.jpeg
+resimler
|resim1.jpeg
|resim2.jpeg
|resim3.jpeg
|resim4.jpeg
+başkadosyalar
|dosya.pdf
|dosya.zip
|dosya.mp3
|dosya.ogg
|dosya.jpeg
Siz bu iç içe geçmiş dosya yığını içinden, sonu .jpeg ile bitenleri tek bir yerde toplamak istiyorsunuz. Elbette, eğer isterseniz bu .jpeg dosyalarını tek tek elle bulup istediğiniz yere taşıyabilirsiniz. Ama bu yöntem bir Python programcısına yakışmaz, değil mi?
Python programcıları bu tür angaryaları kendi yapmak yerine Python’a yaptırmayı tercih eder. O yüzden biz de bu işi yapmak için Python’dan yararlanacağız.
os
modülünün walk()
fonksiyonunu kullanarak bu görevi rahatlıkla yerine
getirebilirsiniz.
Peki ama nasıl?
Öncelikle şu kodlar yardımıyla, yukarıdaki sözünü ettiğimiz dosya-dizin yapısını oluşturalım. Böylece daha somut bir yapı üzerinde çalışma imkanı elde etmiş oluruz:
import os
uzantılar = ['txt', 'doc', 'xls',
'jpeg', 'pdf', 'zip',
'mp3', 'ogg', 'jpeg']
şablon1 = ['{}.{}'.format('dosya', i) for i in uzantılar[:4]]
şablon2 = ['resim{}.{}'.format(i, uzantılar[-1]) for i in range(1, 5)]
şablon3 = ['{}.{}'.format('dosya', i) for i in uzantılar[4:]]
dosyalar = [('anadizin', şablon1),
('resimler', şablon2),
('başkadosyalar', şablon3)]
os.makedirs(os.sep.join([dosya[0] for dosya in dosyalar]))
for dizin, şablon in dosyalar:
for s in şablon:
open(os.sep.join([dizin, s]), 'w')
os.chdir(dizin)
Bu kodlarda, şu ana kadar görmediğimiz, öğrenmediğimiz hiçbir şey yok. Bu kodları rahatlıkla anlayabilecek kadar Python bilgisine sahipsiniz.
Dosya-dizin yapımızı oluşturduğumuza göre, os
modülünün walk()
fonksiyonunu bu yapı üzerinde nasıl kullanacağımıza geçebiliriz.
Şimdi ‘anadizin’ adlı klasörün bulunduğu dizin içinde etkileşimli kabuğu başlatalım ve şu komutları verelim:
>>> for i in os.walk('anadizin'):
... print(i)
Buradan şu çıktıyı alacağız:
('anadizin', ['resimler'], ['dosya.doc', 'dosya.jpeg',
'dosya.txt', 'dosya.xls'])
('anadizin\\resimler', ['başkadosyalar'], ['resim1.jpeg',
'resim2.jpeg', 'resim3.jpeg', 'resim4.jpeg'])
('anadizin\\resimler\\başkadosyalar', [], ['dosya.jpeg',
'dosya.mp3', 'dosya.ogg', 'dosya.pdf', 'dosya.zip'])
İnceleme kolaylığı açısından bu çıktının ilk kısmını ele alalım:
('anadizin', ['resimler'], ['dosya.doc', 'dosya.jpeg',
'dosya.txt', 'dosya.xls'])
Gördüğünüz gibi, burada üç öğeli bir demet var. Çıktının diğer kısımlarını da
incelerseniz aynı yapıyı göreceksiniz. Dolayısıyla os.walk()
komutu bize şu
üç öğeden oluşan bir demet verir:
(kökdizin, altdizinler, dosyalar)
Yukarıdaki çıktıyı incelediğinizde bu yapıyı rahatlıkla görebilirsiniz:
kökdizin => 'anadizin'
altdizinler => ['resimler']
dosyalar => ['dosya.doc', 'dosya.jpeg',
'dosya.txt', 'dosya.xls']
kökdizin => 'anadizin\\resimler'
altdizinler => ['başkadosyalar']
dosyalar => ['resim1.jpeg', 'resim2.jpeg',
'resim3.jpeg', 'resim4.jpeg']
kökdizin => 'anadizin\\resimler\\başkadosyalar'
altdizinler => []
dosyalar => ['dosya.jpeg', 'dosya.mp3',
'dosya.ogg', 'dosya.pdf',
'dosya.zip']
Mesela bu üç öğeli demet içinden yalnızca dosyaları almak isterseniz şöyle bir komut verebilirsiniz:
>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
... print(dosyalar)
Burada, os.walk('anadizin')
komutunun bize sunduğu üç öğeli demetin her bir
öğesini, şu satır yardımıyla tek tek kökdizin, altdizinler ve dosyalar
adlı değişkenlere atıyoruz:
>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
... ...
Sonra da bu üçlü içinden, dosyalar adlı değişkeni ekrana yazdırıyoruz:
>>> print(dosyalar)
Bu da bize şöyle bir çıktı veriyor:
['dosya.doc', 'dosya.jpeg', 'dosya.txt', 'dosya.xls']
['resim1.jpeg', 'resim2.jpeg', 'resim3.jpeg', 'resim4.jpeg']
['dosya.jpeg', 'dosya.mp3', 'dosya.ogg', 'dosya.pdf', 'dosya.zip']
Gördüğünüz gibi, bu çıktıda ‘anadizin’ ve bunun altındaki bütün dizinlerde yer
alan bütün dosyalar var. Bu konunun başında walk()
fonksiyonunu tanımlarken
dediğimiz gibi, walk()
fonksiyonu gerçekten de dizinler içinde ‘yürünmesini’
sağlıyor.
Bu fonksiyonu daha iyi anlamak için birkaç deneme daha yapalım:
>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
... print(altdizinler)
...
['resimler']
['başkadosyalar']
Bu da bize ‘anadizin’ içindeki alt dizinlerin isimlerini veriyor.
Bir de kökdizin değişkeninin ne olduğuna bakalım:
>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
... print(kökdizin)
...
anadizin
anadizin\resimler
anadizin\resimler\başkadosyalar
Burada da o üçlü değişkenler arasından kökdizin’i yazdırdık ve gördük ki bu değişken bize bütün kök dizinlere ilişkin yol bilgilerini, yani dizinlerin adresini veriyor. Dolayısıyla kökdizin değişkeni ile dosyalar değişkenini birleştirerek bir dosyanın tam adresini elde edebiliriz.
Dikkatlice bakın:
>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
... for dosya in dosyalar:
... print(os.sep.join([kökdizin, dosya]))
...
anadizin\dosya.doc
anadizin\dosya.jpeg
anadizin\dosya.txt
anadizin\dosya.xls
anadizin\resimler\resim1.jpeg
anadizin\resimler\resim2.jpeg
anadizin\resimler\resim3.jpeg
anadizin\resimler\resim4.jpeg
anadizin\resimler\başkadosyalar\dosya.jpeg
anadizin\resimler\başkadosyalar\dosya.mp3
anadizin\resimler\başkadosyalar\dosya.ogg
anadizin\resimler\başkadosyalar\dosya.pdf
anadizin\resimler\başkadosyalar\dosya.zip
Bildiğiniz gibi, dosya değişkeninin bize verdiği veri tipi bir listedir. O
yüzden bu listenin öğelerini tek tek alabilmek için bu liste üzerinde de bir
for
döngüsü kurduğumuza dikkat edin.
Eğer yukarıdaki dizinler içinde yer alan bütün .jpeg dosyalarını listelemek istersek de şöyle bir kod yazabiliriz:
>>> for kökdizin, altdizinler, dosyalar in os.walk('anadizin'):
... for dosya in dosyalar:
... if dosya.endswith('.jpeg'):
... print(dosya)
...
dosya.jpeg
resim1.jpeg
resim2.jpeg
resim3.jpeg
resim4.jpeg
dosya.jpeg
Gördüğünüz gibi, os.walk()
fonksiyonu gayet pratik ve kullanışlı bir araç.
os.environ¶
os
modülünün environ adlı niteliği, kullandığımız işletim sistemindeki
çevre değişkenleri hakkında bilgi edinmemizi sağlar.
Bu nitelik alelade bir sözlüktür. Dolayısıyla bu sözlüğün içinde neler olduğunu şu kodlarla görebilirsiniz:
>>> for k, v in os.environ.items():
... print(k.ljust(10), v)
Sözlük içindeki istediğiniz bir değere nasıl erişeceğinizi biliyorsunuz:
>>> os.environ['HOMEPATH']
'\\Documents and Settings\\fozgul'
>>> os.environ['USERNAME']
'FOZGUL'
Yalnız, Windows ve GNU/Linux işletim sistemlerinde çevre değişkenleri ve bunların adları birbirinden farklı olduğu için, doğal olarak environ niteliği de farklı işletim sistemlerinde farklı çıktılar verir. Birden fazla işletim sistemi üzerinde çalışacak şekilde tasarladığımız programlarda bu duruma dikkat etmeliyiz. Örneğin Windows’ta kullanıcı adını veren çevre değişkeni ‘USERNAME’ iken, GNU/Linux’ta bu değişken ‘USER’ olarak adlandırılır.
os.path¶
os
modülü üzerinde dir()
fonksiyonunu uyguladığınızda, orada path adlı
bir niteliğin olduğunu göreceksiniz. Bu nitelik, kendi içinde pek çok önemli
fonksiyon ve başka nitelik barındırır.
Şimdi bu bölümde os.path
adlı bu niteliğin içeriğini inceleyeceğiz.
os.path.abspath()¶
abspath()
fonksiyonu, bir dosyanın tam yolunun ne olduğunu söyler:
>>> os.path.abspath('falanca.txt')
os.path.dirname()¶
dirname()
fonksiyonu, bir dosya yolunun dizin kısmını verir:
>>> os.path.dirname('/home/istihza/Desktop/falanca.txt')
'/home/istihza/Desktop'
Bu fonksiyonu abspath()
fonksiyonu ile birlikte kullanabilirsiniz:
>>> os.path.dirname(os.path.abspath('falanca.txt'))
'/home/istihza/Desktop'
os.path.exists()¶
exists()
fonksiyonu bir dosya veya dizinin varolup olmadığını kontrol eder:
>>> os.path.exists('/home/istihza/Desktop/falanca.txt')
Eğer böyle bir dosya varsa yukarıdaki kod True
çıktısı, yoksa False
çıktısı verir.
os.path.expanduser()¶
expanduser()
fonksiyonu bilgisayardaki kullanıcıya ait dizinin adresini
verir:
>>> os.path.expanduser('~')
'C:\\Documents and Settings\\fozgul'
veya:
>>> os.path.expanduser('~')
'/home/istihza'
Bu fonksiyonu kullanarak, Windows’ta belirli bir kullanıcı ismi ve dizini de oluşturabilirsiniz:
>>> os.path.expanduser('~denizege')
'C:\\Documents and Settings\\denizege'
os.path.isdir()¶
isdir()
fonksiyonu, kendisine parametre olarak verilen öğenin bir dizin olup
olmadığını sorgular:
>>> os.path.isdir('/home/istihza')
Eğer parametre bir dizin ise True
, eğer bir dosya ise False
çıktısı
alınır.
os.path.isfile()¶
isfile()
fonksiyonu, kendisine parametre olarak verilen öğenin bir dosya
olup olmadığını sorgular:
>>> os.path.isfile('/home/istihza/falance.txt')
Eğer parametre bir dosya ise True
, eğer bir dizin ise False
çıktısı
alınır.
os.path.join()¶
join()
fonksiyonu, kendisine verilen parametrelerden, ilgili işletim
sistemine uygun yol adresleri oluşturur:
>>> os.path.join('dizin1', 'dizin2', 'dizin3') #Windows
'dizin1\\dizin2\\dizin3'
>>> os.path.join('dizin1', 'dizin2', 'dizin3')
'dizin1/dizin2/dizin3'
os.path.split()¶
split()
fonksiyonu, bir yol adresinin son kısmını baş kısmından ayırır:
>>> os.path.split('/home/istihza/Desktop')
('/home/istihza', 'Desktop')
Bu fonksiyonu kullanarak dosya adlarını dizin adlarından ayırabilirsiniz:
>>> dizin, dosya = os.path.split('/home/istihza/Desktop/falanca.txt')
>>> dizin
'/home/istihza/Desktop'
>>> dosya
'falanca.txt'
os.path.splitext()¶
splitext()
fonksiyonu dosya adı ile uzantısını birbirinden ayırmak için
kullanılır:
>>> dosya, uzantı = os.path.splitext('falanca.txt')
>>> dosya
'falanca'
>>> uzantı
'.txt'
Gördüğünüz gibi, kendi içinde pek çok nitelik ve fonksiyon barındıran os.path, kullandığımız işletim sistemine uygun şekilde dizin işlemleri yapabilmemizi sağlayan son derece faydalı bir araçtır.
Gelin isterseniz şimdi biraz bu os.path niteliğinin bazı önemli özelliklerinden söz edelim.
Hatırlarsanız önceki derslerimizde, modüllerin kaynak dosyalarını görmemizi
sağlayan __file__
adlı bir araçtan söz etmiştik. Mesela bu aracı os
modülü üzerinde uyguladığımızda şuna benzer bir çıktı alıyorduk:
>>> os.__file__
'C:\\Python\\lib\\os.py'
Demek ki os
modülünün kaynak kodları bu dizin içinde yer alıyormuş…
Normalde __file__
niteliğini yalnızca modül adlarına uygulayabilirsiniz.
Modüllerin nitelik ve fonksiyonları üzerinde __file__
aracı kullanılamaz:
>>> os.name.__file__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__file__'
>>> os.walk.__file__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__file__'
Ama os
modülünün path niteliği için durum biraz farklıdır:
>>> os.path.__file__
Eğer bu komutu Windows’ta verdiyseniz şu çıktıyı alırsınız:
'C:\Python37\lib\ntpath.py'
Ama eğer bu komutu GNU/Linux’ta verdiyseniz şuna benzer bir çıktı alırsınız:
'/home/python37/lib/python3.7/posixpath.py'
Gördüğünüz gibi, __file__
, os.path üzerinde kullanılabiliyor. Yukarıdaki
çıktılardan anladığımıza göre os.path niteliği Windows’ta ntpath,
GNU/Linux’ta ise posixpath adlı bir modüle atıfta bulunuyor.
Dolayısıyla aslında biz os.path niteliğini kullanırken, eğer Windows’ta isek
ntpath
adlı bir modülü, ama eğer GNU/Linux’ta isek posixpath
adlı bir
modülü içe aktarmış oluyoruz.
Eğer os.path adlı ortak bir arayüz olmasaydı, yukarıda os.path başlığı
altında incelediğimiz araçları kullanabilmek için, kullandığımız işletim
sistemine göre posixpath
veya ntpath
modüllerinden uygun olanını
kendimiz elle içe aktarmak zorunda kalacaktık:
if os.name == 'nt':
import ntpath as path
else:
import posixpath as path
Ama Python programlama dilinin bize os.path adlı niteliği sunmuş olması
sayesinde Windows işletim sistemi için ntpath
, GNU/Linux işletim sistemi
için ise posixpath
modülünü ayrı ayrı içe aktarmamıza gerek kalmıyor. Bütün
işi bizim yerimize Python hallediyor. Böylece farklı işletim sistemlerine
ilişkin birbirinden farklı işlemleri, os.path adlı tek bir arayüz üzerinden
gerçekleştirebiliyoruz.
Önemli Not
Sorularınızı yorumlarda dile getirmek yerine Yazbel Forumunda sorarsanız çok daha hızlı cevap alabilirsiniz.Belgelerdeki bir hata veya eksiği dile getirecekseniz lütfen yorumları kullanmak yerine Github'da bir konu (issue) açın.
Eğer yazdığınız yorum içinde kod kullanacaksanız kodlarınızı <pre><code> etiketleri içine alın. Örneğin:
<pre><code class="python"> print("Merhaba Dünya!") </code></pre>