11. Modüller¶
Bu bölümde yine çok önemli bir konu olan “modüller”den bahsedeceğiz. Peki nedir modül? “Modül” en basit tanımıyla, ”.py” uzantısına sahip bir dosyadır. Bu tanıma göre, Python’la yazdığınız bütün program dosyaları birer modüldür. Dolayısıyla bir program yazıp bunu “cımbız.py” adıyla kaydettiğinizi varsayarsak, işte bu “cımbız.py” adlı dosya bir modüldür... Buradan yola çıkarak şöyle bir tanım yapabiliriz o halde:
“Fonksiyonlar, deyimler ve ifadelerden oluşan, bu öğeleri içinde barındıran Python dosyalarına modül adı verilir.”
Peki modüller ne işe yarar?
Modüller Python’daki en yararlı öğelerden bir tanesidir. Bir modül içinde tanımladığımız fonksiyonları başka bir programa aktarabilir, bu fonksiyonları bir daha yazmak zorunda kalmadan tekrar tekrar kullanabiliriz.
Modüller Python’a güç ve esneklik kazandıran öğelerdir. Etrafta, emrimize amade bir şekilde bekleyen binlerce hazır modül bulunur. Bu modüllerden bir kısmı Python’un içindedir, bir kısmı ise internetten indirilebilmektedir. Hazır modülleri kullanarak Python’da inanılmaz işler başarabilirsiniz. Örneğin Tkinter adlı bir modül sayesinde Python’la arayüzlü programlar tasarlayabilirsiniz... Eğer matematiğe meraklıysanız math modülünü kullanarak karmaşık işlemleri son derece kolay bir şekilde halledebilirsiniz... Etrafta bunlar gibi bir yığın modül bulunur.
Python’un içinde yer alan modüllerin listesine http://www.python.org/doc/3.0.1/modindex.html adresinden ulaşabilirsiniz.
Yukarıda söylediğimiz sözler kulağa biraz anlaşılmaz geliyor olabilir. Ama hiç dert etmeyin. İlerleyen sayfalarda modül konusunu ayrıntılı olarak inceleyeceğiz. O halde lafı daha fazla dolandırmadan işe koyulalım.
11.1. Modülleri İçe Aktarmak (importing modules)¶
Python’da bir modülü kullanabilmek için, o modülü öncelikle “içe aktarmamız” gerekiyor. Burada “içe aktarmak”tan kasıt, söz konusu modüle ait özellikleri başka bir dosyanın içine taşımaktır. Bir modül içe aktarıldığında, o modüle ait özellikler, modülün aktarıldığı dosya içinden de kullanılabilecektir. Bu söylediklerimiz kafanızı karıştırmasın. Şimdi bu anlattıklarımızın ne demek olduğunu çok basit örneklerle açıklayacağız.
Python’da os adlı bir modül bulunur. Bu modül Python’un en temel ve en önemli modüllerinden bir tanesidir. Şimdi bir modülün ne olup ne olmadığını anlayabilmek için etkileşimli kabukta aşağıdaki komutu verelim. Bu komut yardımıyla bu os adlı modülün içine bakacağız:
>>> dir(os)
Ne oldu? Python bize bir hata mesajı gösterdi, değil mi? Bu gayet normal. Çünkü biraz önce de söylediğimiz gibi, bir modülü kullanabilmek için öncelikle o modülü içe aktarmamız (import) gerekiyor. Hemen bu işlemi nasıl yapacağımıza bakalım:
>>> import os
Bu komut yardımıyla Python’a şu emri vermiş oluyoruz: “Ey Python! ‘os’ adlı modülü içe aktar, ki ben bu modülün bana sunduğu nimetlerden faydalanabileyim...“
Bu emrimizi alan Python sessizce alt satıra geçecektir. Buraya kadar her şey normal. Bu yaptığımız işleme “içe aktarma” adı veriliyor. Yani biz bu işlemle, os adlı modülü içe aktarmış olduk. Artık bu modülün bütün özelliklerinden yararlanabiliriz. Öncelikle bu modülün içine bakalım neler varmış:
>>> dir(os)
['F_OK', 'MutableMapping', 'O_APPEND', 'O_BINARY', 'O_CREAT', 'O_EXCL', 'O_NOINH
ERIT', 'O_RANDOM', 'O_RDONLY', 'O_RDWR', 'O_SEQUENTIAL', 'O_SHORT_LIVED', 'O_TEM
PORARY', 'O_TEXT', 'O_TRUNC', 'O_WRONLY', 'P_DETACH', 'P_NOWAIT', 'P_NOWAITO', '
P_OVERLAY', 'P_WAIT', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'W_
OK', 'X_OK', '_Environ', '__all__', '__builtins__', '__doc__', '__file__', '__na
me__', '__package__', '_copyreg', '_execvpe', '_exists', '_exit', '_get_exports_
list', '_keymap', '_make_stat_result', '_make_statvfs_result', '_pickle_stat_res
ult', '_pickle_statvfs_result', '_putenv', '_unsetenv', '_wrap_close', 'abort',
'access', 'altsep', 'chdir', 'chmod', 'close', 'closerange', 'curdir', 'defpath'
, 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'errno', 'error', 'exe
cl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'ext
sep', 'fdopen', 'fstat', 'fsync', 'getcwd', 'getcwdb', 'getenv', 'getpid', 'isat
ty', 'linesep', 'listdir', 'lseek', 'lstat', 'makedirs', 'mkdir', 'name', 'open'
, 'pardir', 'path', 'pathsep', 'pipe', 'popen', 'putenv', 'read', 'remove', 'rem
ovedirs', 'rename', 'renames', 'rmdir', 'sep', 'spawnl', 'spawnle', 'spawnv', 's
pawnve', 'startfile', 'stat', 'stat_float_times', 'stat_result', 'statvfs_result
', 'strerror', 'sys', 'system', 'times', 'umask', 'unlink', 'urandom', 'utime',
'waitpid', 'walk', 'write']
Gördüğünüz gibi, os modülü içinde bir hayli araç bulunuyor. Peki bu os modülü ne işe yarar? İngilizce bilen arkadaşlarım şu komutu kullanarak bu modülün belgelendirme dizisine ulaşabilir (Belgelendirme dizilerinin ne olduğunu fonksiyonlar bölümünde işlemiştik...):
>>> print(os.__doc__)
İngilizce bilmeyen arkadaşlarım için bu modülün ne işe yaradığını biz söyleyelim:
os modülü Python içindeki en önemli modüllerden bir tanesidir. Bu modül, kullandığımız işletim sistemine ilişkin bazı önemli işlemler yapmamızı sağlar. Ayrıca bu modülden yararlanmak, birden fazla platform üzerinde çalışan programlar yazmanızı da kolaylaştıracaktır. Bu modülü ayrı bir başlık altında daha detaylı bir şekilde inceleyeceğiz. Ama şimdilik isterseniz bu modülle ilgili birkaç örnek yaparak modüller konusuna biraz olsun ısınmanızı kolaylaştırmaya çalışalım:
En başta da dediğimiz gibi, bir modülü kullanabilmek için öncelikle o modülü içe aktarmamız gerekiyor. Bunu sık sık tekrar ediyorum, çünkü Python’u öğrenenlerin en çok yaptığı hatalardan biri de bir modülü içe aktarmadan kullanmaya çalışmaktır... Şu halde hemen os modülünü içe aktaralım:
>>> import os
Eğer etkileşimli kabuk üzerinde çalışıyorsanız, bu modülü her oturumda bir kez içe aktarmak yeterli olacaktır.
Şimdi şu kodlara bakalım:
>>> import os
>>> if os.name == "posix":
... print("Merhaba GNU/Linux kullanıcısı... Stallman'a benden selam söyle!")
>>> elif os.name == "nt":
... print("Merhaba Windows kullanıcısı... Gates'e benden selam söyle!")
Eğer kullandığınız sistem GNU/Linux ise yukarıdaki kodları çalıştırdığınızda “Merhaba GNU/Linux kullanıcısı...” çıktısı verilecek, eğer Windows kullanıyorsanız “Merhaba Windows kullanıcısı...” çıktısı verilecektir. İsterseniz bu kodları biraz inceleyelim:
Öncelikle os modülünü içe aktarıyoruz. Çünkü bu modülü ve içindeki nitelikleri kullanabilmek için ilk yapmamız gereken şey bu modülü içe aktarmaktır. Modülü bir kez içe aktardıktan sonra “dir(os)” çıktısında görünen bütün niteliklerden, metotlardan ve fonksiyonlardan faydalanabiliriz. os modülü içinde, işletim sistemlerine ilişkin bazı işlemleri yerine getirmemizi sağlayacak araçlar bulunur. Eğer “os(dir)” çıktısına bakacak olursanız, orada name adlı bir ifade görürsünüz. “name” kelimesinin anlamı “isim”dir. Dolayısıyla bu ifade bize kullandığımız işletim sisteminin ismini söyleyecektir. os modülü içinde şu isimler tanımlanmıştır:
'posix', 'nt', 'mac', 'os2', 'ce', 'java', 'riscos'
Şimdi etkileşimli kabukta os modülünü içe aktardıktan sonra şu komutu verin:
>>> print(os.name)
Bu komut, kullandığınız işletim sistemine göre farklı çıktılar verecektir. Eğer GNU/Linux dağıtımlarından birini kullanıyorsanız yukarıdaki komuttan alacağınız çıktı “posix” olacaktır. Eğer Windows kullanıyorsanız bu komut size “nt” cevabını verir. Yok eğer siz bir Macintosh kullanıcısıysanız bu komuttan alacağınız cevap “mac” olacaktır...
Bu ifadeler arasında görünen “os2”, OS/2 adlı işletim sistemini, “ce” Windows CE işletim sistemini, “java” JavaOS işletim sistemini, “riscos” ise RISC OS işletim sistemini temsil eder...
Burada os modülü içindeki bir niteliği nasıl kullandığımıza dikkat edin: os + ”.” + name. Burada “modül_adı” + “nokta” + “istenen_nitelik” yolunu izliyoruz.
Biz burada “print(os.name)” komutuyla aslında Python’a şöyle bir emir vermiş oluyoruz: “os adlı modülünün “name” adlı niteliği aracılığıyla bana kullandığım işletim sisteminin adını söyle!“
Gelin isterseniz yine os modülü içinde yer alan araçlardan biriyle ilgili bir örnek daha yapalım:
>>> print(os.getcwd())
Bu komut bize, o anda hangi dizin içinde çalışıyorsak o dizinin adını verecektir. getcwd() adlı fonksiyonu da “dir(os)” çıktısı içinde görebilirsiniz. Bu arada, getcwd‘nin bir fonksiyon olduğuna dikkat edin. Bu araç bir fonksiyon olduğu için bunu parantezlerle kullanmayı unutmuyoruz. Biraz önce gördüğümüz name niteliği ise bir fonksiyon değil, os modülü içinde yer alan değişkenlerden biridir.
Burada da “print(os.getcwd())” komutuyla Python’a şu emri veriyoruz: “os adlı modülün “getcwd()” adlı niteliği aracılığıyla bana şu anda hangi dizinde çalıştığımı göster.“
Bu arada, eğer os modülünün içeriğini merak ediyorsanız, bu dosyayı inceleyebilirsiniz. Bu modülün sisteminizde nerede bulunduğunu öğrenmek için şöyle bir komuttan yararlanabilirsiniz:
>>> os.__file__
Bu komut, size os modülünün hangi klasör içinde olduğunu söyleyecektir...
Dediğimiz gibi, ilerleyen sayfalarda bu os modülünü daha detaylı olarak inceleyeceğiz. Burada amacımız sadece modül konusuna sizleri ısındırmak...
Dilerseniz şimdi baştan beri söz ettiğimiz “içe aktarma” mevzuunu biraz deşelim...
Dedik ki, bir modülü herhangi bir şekilde kullanabilmek için öncelikle o modülü içe aktarmamız gerekiyor. Yabancılar bu kavrama “import” diyorlar... Python’da bir modülü birkaç farklı şekilde içe aktarabiliyoruz:
- import modül
- from modül import nitelik_adı
- from modül import *
- import modül as takma_ad
Peki bu biçimler arasındaki farklar nedir? Tek tek bakalım:
import modül
Python’da bir modülü bu şekilde içe aktardığımız zaman o modülün ismi dahil bütün nitelikleri kullanılabilir duruma gelir. Bir örnek verelim:
>>> import os
>>> print(os.name)
Burada os adlı modülü “import os” biçimini kullanarak içe aktardığımız için, bu modül içinde bulunan niteliklerden biri olan name‘yi kullanabiliyoruz. os modülü içindeki nitelikleri kullanabilmek için “os.nitelik” yapısını kullanmamız gerekiyor.
Bir modülü bu şekilde içe aktardığımızda, o modülün kendi ismi de içe aktarılmış olur. Bu ne demek? Şu örneğe bakalım:
>>> dir(os)
Modülümüzü “import os” diyerek içe aktardığımız için “dir(os)” komutu çalışıyor. Bunun sebebi os isminin de içe aktarılmış olmasıdır. Bunu biraz sonra daha iyi anlayacağız.
11.1.1. from modül import nitelik_adı¶
Modüllerimizi “from modül import nitelik_adı” biçimini kullanarak da içe aktarabiliyoruz. Bir modülü bu şekilde içe aktardığımız zaman ortaya bazı kullanım farkları çıkacaktır. Şu örneğe bakalım:
>>> from os import getcwd
Burada yaptığımız şey, os modülünün getcwd adlı niteliğini içe aktarmaktan ibarettir. Burada modülümüzün tek bir niteliğini içe aktarmış olduk. Ayrıca kullanımda da şöyle bir fark ortaya çıktı:
>>> print(getcwd())
'/home/istihza/Desktop/'
Gördüğünüz gibi, bu defa getcwd()’nin başına “os.” ifadesini koymadık. Artık “os.getcwd()” demek yerine sadece “getcwd()” komutunu kullanabiliyoruz. Ancak modülümüzü bu biçimde içe aktardığımızda sadece belirtilen nitelik kullanılabilir durumda olacaktır. Yani bu durumda os modülünün getcwd() niteliği dışındaki hiç bir niteliğini kullanamıyoruz. Mesela burada name niteliğinden yararlanamayacağız:
>>> print(name)
NameError: name 'name' is not defined
Eğer getcwd() ile birlikte name niteliğini de kullanmak istersek kodumuzu şöyle yazmamız gerekir:
>>> from os import getcwd, name
Artık şu komutlar çalışacaktır:
>>> print(getcwd())
>>> print(name)
Gördüğünüz gibi, kullanmak istediğimiz her niteliği ayrı ayrı içe aktarıyoruz. Eğer yazacağınız programda bir modülün sadece tek bir niteliğini kullanacaksanız koca bir modülün tamamını içe aktarmak yerine, bu biçimi tercih edebilirsiniz...
Biraz önce, “bir modülü bu import modül_adı biçimiyle içe aktardığımızda, o modülün kendi ismi de içe aktarılmış olur,” demiştik. Şimdi bunun ne demek olduğunu göreceğiz:
>>> dir(os)
NameError: name 'os' is not defined
Gördüğünüz gibi, modülümüzü from modül import modül_adı biçiminde içe aktardığımızda os adını kullanamıyoruz. Çünkü, dediğimiz gibi, bu şekilde içe aktarmalarda modül adı aktarım listesine dahil olmayacaktır.
11.1.2. from modül import *¶
Modülümüzü içe aktarmak için kullanabileceğimiz bir başka yol da “from modül import * biçimini tercih etmektir. Eğer bir modülü bu şekilde içe aktaracak olursak, o modül içindeki, ismi “_” ile başlayanlar hariç bütün nitelikler kullanılabilir hale gelecektir. Örnek verelim:
>>> from os import *
>>> print(name)
>>> print(getcwd())
Gördüğünüz gibi, “from os import *” yapısını kullandığımızda, modül ismini kullanmadan (yani “os.” kısmını atarak), modüle ait nitelikleri kullanabiliyoruz. Ancak bu yapının çok önemli bir riski vardır. Bir modülü bu şekilde içe aktardığımızda, o modüle ait bütün nitelikler doğrudan o anda içinde çalıştığımız isim alanına dahil olacaktır. “isim alanı” kavramını önceki derslerimizden hatırlıyorsunuz. İsterseniz bu riski şöyle bir örnekle somutlaştıralım.
Diyelim ki şöyle bir kodumuz var:
>>> name = "istihza.com"
Eğer biz bu kodun bulunduğu bir programda “from os import *” komutunu verecek olursak programımızı darmadağın ederiz... Nasıl mı? Şuna bakın şimdi:
>>> name = "istihza.com"
>>> print(name)
istihza.com
Şimdi os modülünü içe aktarıyoruz:
>>> from os import *
>>> print(name)
posix
Gördüğünüz gibi, os modülünü içe aktarmamızla birlikte önceden tanımlamış olduğumuz name adlı değişken siliniverdi... Muhtemelen yazacağınız programlarda böyle bir şeyin başınıza gelmesini istemezsiniz... Bu tür durumları engellemenin en iyi yolu modülü “import modül_adı” şeklinde içe aktarmaktır:
>>> name = "istihza.com"
>>> print(name)
istihza.com
>>> import os
>>> print(os.name)
posix
>>> print(name)
istihza.com
Bu defa, os modülüne ait name niteliğini kullanabilmek için “os.” ifadesini de eklememiz gerektiğinden, daha önce tanımladığımız “name” adlı değişkeni kaybetmemiş oluyoruz...
11.1.3. import modül as takma_ad¶
Python’da bazı modül isimleri uzundur. Örneğin multiprocessing adlı modülü şu şekilde içe aktardığımızı varsayalım:
>>> import multiprocessing
Bu modülü bu şekilde içe aktardığımızda modülün niteliklerine erişmek için her defasında modül adını da belirtmemiz gerekecek:
>>> multiprocessing.nitelik_adı
Eğer her defasında “multiprocessing” yazmak zor geliyorsa modülü şu şekilde içe aktarmayı tercih edebiliriz:
>>> import multiprocessing as mp
Böylece normalde “multiprocessing” yazmamız gereken yerlere sadece “mp” yazabileceğiz:
mp.nitelik_adı
Bu yöntemi ayrıca modül adının sizin programınızdaki kodlarla çakışmaya neden olacağını düşündüğünüz durumlarda da kullanmayı tercih edebilirsiniz.
Gördüğünüz gibi Python’da bir modülü içe aktarmanın pek çok yolu var. Peki bunlardan hangisini tercih etmeliyiz? Bunlar içinde en sağlıklı olanı “import modül_adı”, en pratik olanı ise “from modül_adı import *” şeklinde gösterdiğimiz içe aktarma biçimidir. Kullandığımız modülün “from modül_adı import *” şeklinde içe aktarılmasının sakıncalı olmadığından emin değilsek “import modül_adı” biçimini tercih etmeliyiz. Yani çoğunlukla tercih edeceğimiz biçim “import modül_adı” olacaktır... Bazı modülleri “from modül_adı import *” şeklinde içe aktarmamızda sakınca yoktur. Mesela grafik arayüzlü programlar yapmak için kullanacağımız tkinter adlı modül bunlardan biridir...
11.2. os ve sys Modülleri¶
Bu bölümde Python içindeki modüllerden en önemli iki tanesi olan os ve sys adlı modülleri inceleyeceğiz. Bu iki modül Python’un en temel modülleridir ve mutlaka öğrenilmeleri gerekir.
O halde ilk modülümüz olan os‘tan başlayalım...
11.2.1. os Modülü¶
os Modülü Python’un en temel modüllerinden bir tanesidir. Bu modüle daha önce değinmiştik. Burada bu modülü, biraz daha ayrıntısına inerek incelemeye çalışacağız.
Bildiğiniz gibi, bir modülü kullanabilmek için öncelikle o modülü içe aktarmamız gerekiyor:
>>> import os
Yine bildiğiniz gibi, modüllerimizi birkaç farklı şekilde içe aktarabiliyoruz. Ama mevcut yöntemler içinde en sağlıklısı “import os” biçimidir.
İçe aktardığımız bu modülün içeriğini görmek istersek, daha önce pek çok kez kullandığımız dir() fonksiyonundan yararlanabiliriz:
>>> dir(os)
dir() fonksiyonuyla os modülünün içine baktığımızda bu modülün epey bir niteliği olduğunu görüyoruz...
“os”, İngilizce’deki “operating system” ifadesinin kısaltmasıdır. Bu ifade “işletim sistemi” anlamına gelir. Dolayısıyla os modülü bize işletim sistemleriyle ilgili işlemler yapma imkanı verir. Eğer bu modülle ilgili yardım almak isterseniz şu komutları kullanabilirsiniz:
>>> help(os)
...veya...
>>> print(os.__doc__)
Eğer İngilizce biliyorsanız, yukarıdaki komutların çıktılarına bakarak os modülünün ne işe yaradığına dair bazı bilgiler edinebilirsiniz. Eğer İngilizce bilmiyorsanız ziyanı yok. Biz size yardımcı olmaya çalışacağız.
Gelin isterseniz şimdi “dir(os)” komutu ile karşımıza gelen listedeki niteliklerin en önemlilerini incelemeye koyulalım.
11.2.1.1. name Niteliği¶
“name” kelime olarak “isim” anlamına gelir. os modülüne ait bir nitelik olan name, bize kullandığımız işletim sisteminin adını verir. Bununla ilgili şöyle bir örnek verebiliriz:
>>> print(os.name)
Kullandığımız işletim sistemine göre bu komuttan şu çıktılardan birini alırız:
'posix', 'nt', 'mac', 'os2', 'ce', 'java', 'riscos'
Bunların ne anlama geldiğini daha önce söylemiştik.
os modülünün name niteliğini kullanarak, yazdığınız kodların birkaç sisteme birden duyarlı olmasını sağlayabilirsiniz. Mesela şöyle bir örnek verelim:
>>> if os.name == "posix": #Eğer işletim sistemi GNU/Linux ise...
... print("Sisteme hoşgeldiniz!")
>>> elif os.name == "nt": #Eğer işletim sistemi Windows ise...
... print("Kullandığınız işletim sistemi desteklenmemektedir.")
Burada kullanıcının sahip olduğu işletim sistemine göre kullanıcıyı kabul ediyoruz veya etmiyoruz... Bu arada, yukarıdaki kodları çalıştırabilmek için öncelikle os modülünü içe aktarmış olmanız gerektiğini biliyorsunuz...
os modülünün name niteliği üzerine söylenecek fazla bir şey yok. Ne işe yaradığı zaten adından da belli oluyor. O yüzden isterseniz hemen başka bir niteliği tanımaya girişelim.
11.2.1.2. getcwd Fonksiyonu¶
getcwd os modülü içinde bulunan bir fonksiyondur. Biz bu fonksiyona daha önce de değinmiştik. Orada da dediğimiz gibi, bu fonksiyon o anda bulunduğumuz dizinin adını verir:
>>> print(os.getcwd())
'/home/istihza'
Demek ki ben şu anda “/home/istihza” dizininin altında çalışıyormuşum. Elbette işletim sisteminize ve o anda bulunduğunuz dizine bağlı olarak bu komutun çıktısı sizde farklı olacaktır. Örneğin bu fonksiyonu Windows altında çalıştırmak istersek...
>>> print("Şu anda bulunduğunuz dizinin adı:\n", os.getcwd())
'Şu anda bulunduğunuz dizinin adı:
C:\\Documents and Settings\\ISTIHZA'
os modülünün bu getcwd() adlı fonksiyonu, yazdığımız pek çok programda işimizi kolaylaştırabilecek bir araçtır.
11.2.1.3. listdir Fonksiyonu¶
“listdir” kelimesi “list directory” (dizini listele) ifadesinin kısaltmasıdır. Bu fonksiyonu kullanarak, istediğimiz bir dizinin içeriğini gösterebiliriz:
>>> os.listdir("/home/istihza/")
Burada ben “/home/istihza” dizininin içeriğini listeledim. Eğer Windows üzerindeyseniz şöyle bir şey de yapabilirsiniz tabii ki:
>>> os.listdir("C:\\Documents and Settings")
Bu komut “C:\Documents and Settings” altında bulunan bütün dosyaları bir liste halinde verecektir. Eğer o anda içinde bulunduğunuz dizinin içeriğini listelemek isterseniz şöyle bir şey yazabilirsiniz:
>>> mevcut_dizin = os.getcwd()
>>> os.listdir(mevcut_dizin)
Bu komut da o anda bulunduğunuz dizin içinde ne var ne yoksa listeleyecektir.
Eğer mesela bir dizin içindeki, “f” harfiyle başlayan dosyaları listelemek gibi bir niyetiniz varsa şöyle bir kod yazabilirsiniz:
>>> dizin = "/home/istihza/Desktop"
>>> for i in os.listdir(dizin):
... if i[0] == "f":
... print(i)
print() fonksiyonunun gücünü kullanarak şöyle bir çıktı da elde edebilirsiniz:
>>> mevcut_dizin = os.getcwd()
>>> print(*os.listdir(mevcut_dizin), sep=", ")
Böylece hem mevcut dizindeki dosyaları listeledik, hem de her bir öğeyi virgülle ayırdık...
11.2.1.4. chdir Fonksiyonu¶
“chdir” kelimesi, “change directory” (dizin değiştir) ifadesinin kısaltmasıdır. Adından da anlaşılacağı gibi bu fonksiyon o anda içinde bulunduğumuz dizinden çıkıp başka bir dizine geçmemizi sağlar. Mesela:
>>> os.chdir("/usr/share/")
Yukarıdaki komut yardımıyla, o anda bulunduğum dizin içinden çıkıp “/usr/share/” adlı dizinin içine girdim. Bu durumu şu şekilde teyit edebiliriz:
>>> mev_diz = os.getcwd()
>>> os.listdir(mev_diz)
Şu anda “/usr/share/” dizini altında bulunduğum için yukarıdaki kodların çıktısında bu dizinin içeriğini görüyorum. Şimdi bulunduğum dizini tekrar değiştireyim:
>>> os.chdir("/etc/X11/")
>>> os.listdir(os.getcwd())
O anda içinde bulunduğum dizini terkedip “/etc/X11/” dizinine geldiğim için, os.listdir(os.getcwd()) komutu bana “/etc/X11/” dizininin içeriğini listeliyor.
11.2.1.5. curdir Niteliği¶
“curdir” İngilizce’de “current directory” (mevcut dizin) ifadesinin kısaltmasıdır. Bu nitelik daha önce öğrendiğimiz getcwd() fonksiyonuna çok benzer. Bu ikisi arasında anlayış farkı vardır...
Öncelikle curdir niteliğinin ne çıktı verdiğine bakalım:
>>> os.curdir
'.'
Gördüğünüz gibi, bu komuttan bir “nokta” çıktısı alıyoruz... Peki bu ne işe yarıyor? İşletim sistemlerinde mevcut dizini ifade etmek için kullanılan basit karakter dizileri vardır. İşte bu nokta işareti de bunlardan biridir. Mesela bu karakter dizisini şu şekilde kullanabiliriz:
>>> os.listdir(".")
Bu komut bize “os.listdir(os.getcwd())” ile aynı çıktıyı verecektir. Genellikle bütün işletim sistemlerinde mevcut dizini temsil eden karakter dizisi nokta işaretidir. Ama programınızın birden fazla işletim sistemi üzerinde çalışmasını temin etmek için şöyle bir kod yazmayı tercih edebilirsiniz:
>>> os.listdir(os.curdir)
Böylece, programınızın çalıştırıldığı işletim sistemi neyse, “os.curdir” yerine otomatik olarak mevcut dizini temsil eden karakter dizisi yerleştirilecek ve böylece mevcut dizinin içeriği otomatik olarak ekrana dökülecektir...
11.2.1.6. environ Niteliği¶
os modülü içinde bulunan bu environ adlı nitelik esasında bir sözlüktür. Bu sözlük sisteminizdeki çevre değişkenlerine ilişkin bilgileri tutar. Mesela environ niteliğini kullanarak sistemdeki kullanıcı adını öğrenebiliriz:
>>> os.environ["USER"] #Windows'ta "USERNAME"
Kullanıcı dosyalarının bulunduğu dizini elde etmek için ise şöyle bir şey yazabiliriz:
>>> os.environ["HOME"] #Windows'ta "HOMEPATH"
Bilgisayar adı:
>>> os.environ["COMPUTERNAME"] #GNU/Linux'ta buna yakın olarak "LOGNAME" bulunur...
İşlemciye ilişkin bilgiler:
>>> os.environ["PROCESSOR_IDENTIFIER"] #GNU/Linux'ta bulunmaz.
Dediğimiz gibi, environ esasında bir sözlüktür. Dolayısıyla bu sözlüğün içindeki bütün değişkenleri görmek için şöyle bir yol izleyebilirsiniz:
>>> for k, v in os.environ.items():
... print("{0} = {1}".format(k, v)
Mesela kullanıcının masaüstü dizinine gitmek, ardından da masaüstündeki dosyaları listelemek için environ‘dan yararlanabilirsiniz:
>>> os.chdir(os.environ["HOME"] + "/Desktop")
>>> os.listdir(os.curdir)
11.2.1.7. sep Niteliği¶
İşletim sistemleri, dizinleri birbirinden ayırmak için farklı işaretler kullanır. Örneğin os.getcwd() komutunu verdiğimizde, dizin ayraçları açısından GNU/Linux ve Windows’ta farklı sonuçlar alırız:
>>> os.getcwd()
/home/istihza/Desktop #GNU/Linux
C:\\Documents and Settings\\ISTIHZA\\Desktop #Windows
Gördüğünüz gibi, dizin ayraçları birbirinden farklı. Eğer yazdığımız programlarda bu farklılığı göz önünde bulundurmazsak, programlarımız farklı işletim sistemlerinde düzgün çalışmayacaktır. Python bu riske karşı bize os modülü içinde sep adlı bir nitelik sunar. Bu komut farklı sistemlerde farklı çıktılar verecektir:
>>> os.sep
'/' #GNU/Linux
'\\' #Windows
GNU/Linux ve Windows’taki dizin ayraçlarının birbirlerinden farklı olduğuna dikkat edin. Bu sep niteliği sayesinde birden fazla işletim sisteminde çalışabilecek programlar yazma ihtimalimiz artar. Bir örnek verelim:
>>> dizin = os.getcwd() + "\\resimler"
Bu yapı sadece Windows için uygundur. Çünkü biz burada kodumuzun içine doğrudan “\\” ayracını koyarak programımızın GNU/Linux’ta çalışmasını engelledik. Bu şekilde dizin ayraçlarını kodun içine gömmek yerine os.sep‘ten faydalanabiliriz:
>>> dizin = os.getcwd() + os.sep + "resimler"
Bu şekilde Python uygun dizin ayracını otomatik olarak yerine yerleştirecektir.
11.2.1.8. mkdir ve makedirs Fonksiyonları¶
Bu bölümde, os modülü içinde yer alan iki önemli fonksiyondan söz edeceğiz. Bunlar mkdir() ve makedirs() fonksiyonlarıdır. İlk olarak mkdir() fonksiyonuyla başlayalım.
11.2.1.8.1. mkdir() Fonksiyonu¶
os modülü içinde yer alan mkdir adlı fonksiyon yardımıyla bilgisayarımızda yeni dizinler oluşturabiliyoruz. Örneğin:
>>> os.mkdir("DENEME_DİZİNİ")
Böylece o anda çalıştığımız dizin içinde “DENEME_DİZİNİ” adlı yeni bir dizin oluşturmuş olduk.
mkdir() fonksiyonu sadece tek bir dizin oluşturmamıza izin verir. Yani bu fonksiyonu kullanarak birden fazla veya iç içe geçmiş dizinler oluşturamayız. Yani şöyle bir şey yapamayız:
>>> os.mkdir("deneme/test")
Ancak şöyle bir şey yapabiliriz:
>>> os.mkdir("deneme")
>>> os.mkdir("deneme/test")
Yani bu fonksiyonu kullanarak bir dizin oluşturduktan sonra o dizin içinde başka dizinler de oluşturabiliriz. Ayrıca bu fonksiyon yardımıyla aynı anda birden fazla dizin oluşturmak istersek elbette for döngülerinden de yararlanabiliriz:
>>> dizin_listesi = ["Programlar", "Belgeler", "Resimler"]
>>> for i in dizin_listesi:
... os.mkdir(i)
mkdir() fonksiyonu GNU/Linux’ta mode adlı bir parametre daha alır. Bu fonksiyonu kullanarak dizin oluştururken mode adlı parametreye “0755”, “0644” gibi sayılar vererek, oluşturduğunuz klasörün izinlerini belirleyebilirsiniz:
Örneğin şu komut yardımıyla GNU/Linux’ta oluşturduğunuz klasörün izinlerini “0755” olarak ayarlayabilirsiniz:
>>> os.mkdir("dizin", 0755)
Son olarak, eğer os.mkdir() fonksiyonunu kullanarak, halihazırda var olan bir dizin yaratmaya çalışırsanız, Python size bir hata mesajı gösterecektir.
Gelelim makedirs() fonksiyonuna...
11.2.1.8.2. makedirs() Fonksiyonu¶
makedirs() fonksiyonu bize iç içe geçmiş dizinler oluşturma imkanı sağlar:
>>> os.makedirs("dizin1/dizin2")
Bu komut “dizin1” adlı bir dizin, bunun içinde de “dizin2” adlı başka bir dizin oluşturacaktır. Eğer oluşturmaya çalıştığınız dizinler zaten varsa Python bir hata mesajı gösterecektir. Tıpkı mkdir() fonksiyonunda olduğu gibi makedirs() fonksiyonu da kullanılıp kullanılmaması tercihinize kalmış bir mode parametresi sunar:
>>> os.makedirs("falanca/filanca", 0644)
11.2.1.9. rmdir() ve removedirs() Fonksiyonları¶
Bir önceki bölümde os modülünü kullanarak nasıl dizin oluşturacağımızı öğrenmiştik. Bu bölümde ise oluşturduğumuz bu dizinleri silmeyi öğreneceğiz. Bunun için os modülünde yer alan iki adet fonksiyondan yararlanacağız. Bu fonksiyonlardan birinin adı rmdir() öbürü ise removedirs(). Öncelikle rmdir() fonksiyonundan başlayalım:
11.2.1.9.1. rmdir() Fonksiyonu¶
Bu fonksiyon yardımıyla tek bir dizini silebiliyoruz:
>>> os.rmdir("dizin")
Ancak eğer silmek istediğimiz dizinin içi doluysa Python bize bir hata mesajı gösterecektir. Dolayısıyla bu fonksiyonu kullanarak içi dolu dizinleri silemeyiz. Ama diyelim ki elimizde içi boş, ama iç içe geçmiş dizinler varsa bu fonksiyon yardımıyla bunları silebiliriz.
Diyelim ki sistemimizde “dizin1” adlı bir dizin, bunun içinde de “dizin2” adlı boş bir dizin daha var. Biz rmdir() fonksiyonunu kullanarak “dizin1”i silemeyiz. Çünkü “dizin1” boş değildir (“dizin1”in içinde “dizin2” var). Ama istersek “dizin2”yi silebiliriz. Çünkü bu dizinin için boş:
>>> os.rmdir("dizin1/dizin2")
Bu komut yalnızca “dizin2”yi silecek, “dizin1”e ise dokunmayacaktır. Ama eğer “dizin2”yi sildikten sonra “dizin1”in içinde başka hiç bir dosya veya klasör kalmamış, yani “dizin1”in içi boşalmışsa, bu komutu tekrar yazarak “dizin1”i de silebiliriz:
>>> os.rmdir("dizin1")
Gördüğünüz gibi, rmdir() fonksiyonu tek bir boş dizin üzerinde işlem yapabiliyor. Elbette bu fonksiyonu bir for döngüsüne sokarak birden fazla boş dizini de silebilirsiniz...
Sıra geldi removedirs() adlı fonksiyona...
11.2.1.9.2. removedirs() Fonksiyonu¶
Bu fonksiyon genellikle yanlış anlaşılır. Bir defa şunu bilmeliyiz ki bu fonksiyon içi dolu dizinleri silmek için kullanılmaz. Bu fonksiyon birden fazla dizini silmek için de kullanılmaz... Peki bu removedirs() denen fonksiyon ne işe yarar?
Diyelim ki sistemimizde “dizin1” adlı bir dizin, bunun içinde “dizin2” adlı başka bir dizin, bunun içinde de “dizin3” adlı başka bir dizin var. Şimdi şöyle bir komut verelim:
>>> os.removedirs("dizin1/dizin2/dizin3")
Bu komutu alan Python, sondan başa doğru ilerleyecek ve yoluna çıkan bütün boş dizinleri silecektir. Ama Python bu işlem sırasında karşısına çıkan ilk içi dolu dizinde silme işlemini keser... Yani eğer bu üç dizinin üçünün de içi boşsa removedirs() fonksiyonu bu üç dizinin üçünü de siler. Eğer “dizin1”in içinde “dizin2” harici başka dosyalar da varsa, removedirs() fonksiyonu “dizin2” ve “dizin3”ü siler. Eğer “dizin2”nin içinde başka dosyalar varsa, bu fonksiyon sadece “dizin3”ü siler. Eğer “dizin3”ün içinde başka dosyalar var ise hiç bir şey silmez... Eğer bu dediklerim biraz karışık geldiyse, kendi kendinize bazı denemeler yaparak removedirs() fonksiyonunun tam olarak ne iş yaptığını daha net olarak görebilirsiniz.
Peki rmdir() ve removedirs() fonksiyonlarından hiçbiri içi dolu dizinleri silemiyorsa, biz içi dolu dosyaları silmek istersek ne yapacağız? Hiç endişelenmeyin. Python’da bunun için kullanılan başka araçlar vardır. Onları da bir iki bölüm sonra göreceğiz.
11.2.1.10. rename Fonksiyonu¶
Şimdiye kadar Python’daki os modülünü kullanarak dizin oluşturmayı (mkdir/makedirs) ve oluşturduğumuz bu dizinleri silmeyi (rmdir/removedirs) öğrendik. Peki ya biz oluşturduğumuz dizinlerin adını değiştirmek istersek ne yapacağız? İşte burada devreye rename() adlı fonksiyon girecek.
rename() fonksiyonunun formülü şudur:
>>> os.rename("dizinin_eski_adı", "dizinin_yeni_adı")
Diyelim ki sistemimizde “documents” adlı bir dizin var ve biz bu dizinin adını “belgeler” olarak değiştirmek istiyoruz. İşte burada os.rename() fonksiyonu işimizi görecektir:
>>> os.rename("documents", "belgeler")
Bu fonksiyon için, üzerinde işlem yapacağı dizinin boş olup olmaması farketmez. rename() fonksiyonu hem boş hem de dolu dizinlerin isimlerini başarıyla değiştirebilir.
11.2.1.11. system Fonksiyonu¶
os modülü içinde yer alan system adlı fonksiyon, oldukça faydalı bir araçtır. Ayrıca bu araç, os modülü içindeki fonksiyon ve nitelikler arasında en sık kullanılanlardan biridir. Bu fonksiyon yardımıyla işletim sistemimize ilişkin komutları Python içinden çalıştırabiliriz:
if os.name == "nt":
os.system("'C:\Program Files\Internet Explorer\iexplore.exe' www.istihza.com")
elif os.name == "posix":
os.system("firefox www.istihza.com")
Eğer kullandığımız sistem Windows ise Internet Explorer programını kullanarak “istihza.com” adresine gidiyoruz. Eğer kullandığımız sistem GNU/Linux ise aynı işlemi Firefox kullanarak yapıyoruz...
Herhalde söylememize gerek yok... system adlı bu fonksiyon, sistem komutlarını çalıştırdığı için, bu fonksiyonu kullanırken dikkatli olmamız gerekir...
11.2.1.12. os.path Modülü¶
Aslında Python’da os.path veya path adlı bir modül yoktur. Bunun yerine, GNU/Linux için posixpath ve Windows için nt.path adlı iki farklı modül bulunur. os.path adı bu iki modül yerine kullanılan bir “takma ad”dır. Biz kullandığımız sisteme göre doğrudan bu iki modülden birini içe aktarmakla uğraşmıyoruz. Bizim yapmamız gereken tek şey os modülünü içe aktarıp, path niteliğine ise os.path biçimini kullanarak erişmektir. Python kullandığımız sistemi kendisi tespit edip, ntpath veya posixpath modüllerinden birini otomatik olarak içe aktaracaktır. Şimdi etkileşimli kabukta şu komutu verelim:
>>> os.path.__file__
Bu komutun çıktısında, kullandığınız işletim sistemine bağlı olarak, os.path isminin hangi dosyaya bağlı olduğu ve bu dosyanın sistemdeki konumu görünecektir. Şimdi bu komutun sizi götürdüğü yere gidip ntpath.py veya posixpath.py dosyalarının içeriğini inceleyin. Bu dosyaların en başında bazı açıklamalar göreceksiniz. Mesela posixpath.py dosyasının en başında şu açıklama var:
Common operations on Posix pathnames. Instead of importing this module directly, import os and refer to this module as os.path. The “os.path” name is an alias for this module on Posix systems; on other systems (e.g. Mac, Windows), os.path provides the same operations in a manner specific to that platform, and is an alias to another module (e.g. macpath, ntpath). Some of this can actually be useful on non-Posix systems too, e.g. for manipulation of the pathname component of URLs.
Bu paragrafta, os.path modülünün, GNU/Linux için yazılmış posixpath modülüne atıfta bulunan bir takma ad olduğundan bahsediliyor. Buradaki açıklamaya göre, os.path modülü başka işletim sistemlerinde de macpath veya ntpath gibi modüllere atıfta bulunan bir takma addır aynı zamanda... Buna benzer bir açıklamayı ntpath.py dosyasında da bulabilirsiniz. Eğer bu açıklamaya etkileşimli kabuktan erişmek isterseniz ne yapmanız gerektiğini biliyorsunuz:
>>> print(os.path.__doc__)
Bu komutun çıktısında, kullandığınız sisteme bağlı olarak farklı açıklamalar göreceksiniz.
Bu ”.py” uzantılı dosyaların bulunduğu dizinde “os.py” adlı bir dosya daha göreceksiniz. İşte bu dosya, biz etkileşimli kabukta “import os” komutunu verdiğimizde içe aktarılan modüldür... En başta modülün ne demek olduğunu tanımlarken söylediğimiz gibi, Python modülleri (çoğunlukla) .py uzantılı birer dosyadır. Bu “os.py” adlı dosyayı açıp içine dikkatlice bakın. Bu bölümde bahsettiğimiz, makedirs, mkdir, removedirs gibi fonksiyonları ve name gibi nitelikleri bu “os.py” adlı modül içinde bulup, bunların nasıl tanımlandığını inceleyebilirsiniz. Bu dosya içindeki her şeyi anlamak zorunda değilsiniz. Sadece göz ucuyla inceleseniz bile Python programlarının nasıl yazılacağı konusunda epey fikir sahibi olabilirsiniz...
“os.py” dosyası içinde şöyle bir kod parçası göreceksiniz:
if "posix" in _names:
import posixpath as path
elif "nt" in _names:
import ntpath as path
Bu bölümün başından beri anlattığımız şeylerin “os.py” dosyası içinde nasıl tanımlandığına dikkat edin. Yukarıdaki kod parçasında, biz etkileşimli kabukta “import os” komutu verdiğimizde, kullandığımız işletim sistemine göre hangi modülün “path” adıyla çağrılacağı belirtiliyor. Buna göre, eğer GNU/Linux kullanıyorsak posixpath adlı modül path takma adıyla çağrılıyor. Aynı şekilde Windows kullanıcıları için de ntpath adlı modül path adıyla içe aktarılıyor...
Şimdi biraz pratik yapalım:
>>> import os
>>> dir(os.path)
Burada, “os.path” adlı modülün içinde neler olduğunu görüyoruz. Kullandığınız sisteme göre “posixpath.py” veya “ntpath.py” dosyalarının içeriğini tekrar kontrol ederseniz, bu listedeki nitelik ve fonksiyonların nasıl tanımlandığını inceleyebilirsiniz...
Şimdi bu modülün içindeki önemli nitelik ve fonksiyonları kısaca inceleyelim:
11.2.1.12.1. os.path.abspath()¶
Bu fonksiyon, bize bir dosyanın tam yolunu verir:
>>> os.path.abspath("falanca.pdf")
os.path.abspath() fonksiyonunun görevi bir dosyanın nerede olduğunu bulmak değildir. Hatta bu fonksiyon, kendisine parametre olarak girdiğiniz dosya adının gerçek olup olmadığıyla dahi ilgilenmez... Bu fonksiyonun görevi, bir dosya adını almak ve bunu o anda içinde bulunulan dizinin sonuna yapıştırmaktır... Mesela bilgisayarınızda olmayan bir dosya adı vermeyi deneyin bu fonksiyona... Örneğin yukarıda verdiğimiz “falanca.pdf” adını kullanın. Diyelim ki o anda içinde bulunduğunuz dizin “home/kullanıcı_adı/Desktop”. Şu halde os.path.abspath(“falanca.pdf”) komutunun çıktısı “home/kullanıcı_adı/Desktop/falanca.pdf” olacaktır. Şu anda bulunduğunuz dizinin ne olduğunu os.getcwd() komutuyla öğrenebileceğinizi biliyorsunuz.
11.2.1.12.2. os.path.basename()¶
Bu fonksiyon bir yol içindeki dosya adını verir bize... Örneğin:
>>> os.path.basename("/home/istihza/Desktop/falanca.pdf")
falanca.pdf
Tıpkı os.path.abspath() fonksiyonunda olduğu gibi, os.path.basename() fonksiyonu da yol adının gerçek olup olmadığıyla ilgilenmez. Yani bu fonksiyonu hayali yol adlarıyla birlikte de kullanabilirsiniz:
>>> os.path.basename("/dangıl/dungul/bangıl/bungul/füzel.pfg")
füzel.pfg
11.2.1.12.3. os.path.exists¶
Bu fonksiyon, bir dosyanın var olup olmadığını kontrol eder. Eğer dosya varsa “True”, yoksa “False” çıktısı verir:
>>> os.path.exists("falanca.txt")
Eğer o anda çalışılan dizin içinde “falanca.txt” adlı bir dosya varsa “True”, yoksa “False” çıktısı alırız. Bu fonksiyonu uzak konumlardaki dosyaların varlığını kontrol etmek için de kullanabiliriz:
>>> os.path.exists("/home/istihza/Desktop/deneme.py")
11.2.1.12.4. os.path.getsize¶
Bu fonksiyon yardımıyla bir dosyanın boyutunu “bayt” cinsinden elde edebiliriz:
>>> os.path.getsize("falanca.odt")
27135
Demek ki “falanca.odt” adlı dosyanın boyutu “27135” baytmış. Yani yaklaşık 27 kilobayt...
11.2.1.12.5. os.path.isdir ve os.path.isfile¶
isdir() fonksiyonu bir “şey”in dizin olup olmadığını kontrol eder. Eğer sorguladığımız şey bir dizin ise bu fonksiyon True değerini, değilse False değerini verir:
>>> os.path.isdir("falanca")
isfile() fonksiyonu ise bir şeyin dosya olup olmadığını kontrol eder:
>>> os.path.isfile("falanca")
11.2.1.12.6. os.path.split¶
İsterseniz bu fonksiyonun ne yaptığına doğrudan bir örnekle bakalım:
>>> os.path.split("/usr/share/harman/harman.py")
('/usr/share/harman', 'harman.py')
Gördüğünüz gibi, bu fonksiyon yol ve dosya adını ayıkladıktan sonra bunları bize bir demet olarak verdi...
11.2.1.12.7. os.path.join¶
os.path modülü içindeki sık kullanılan fonksiyonlardan biri de join‘dir. Bu kelime Türkçe’de “birleştirmek” anlamına gelir. join fonksiyonu, kendisine verdiğimiz parametreleri alıp bir dizin haline getirir. Mesela şu komut o anda içinde bulunulan dizin içindeki, “özel dosyalar” ve “resimler” adlı klasörleri birleştirip, kullanılan işletim sisteminin yapısına uygun bir yol adı oluşturacaktır:
>>> dizin = os.path.join(os.getcwd(), "özel dosyalar", "resimler")
'C:\\Documents and Settings\\ISTIHZA\\Desktop\\özel dosyalar\\resimler'
...veya...
'/home/istihza/Desktop/özel dosyalar/resimler'
11.2.2. sys Modülü¶
Python’daki önemli modüllerden biri de sys adlı modüldür. Bu modül Python sistemiyle ilgili nitelikler ve fonksiyonlar barındırır. os modülünün aksine, sys adlı bu modülün Python dilinde yazılmış bir kaynak kodu yoktur. Bu modül C programlama dili ile yazılmıştır. Dolayısıyla, sistemde “sys.py” adlı bir dosya bulunmadığı için, “sys.__file__” gibi bir komut bu modül üzerinde çalışmayacaktır.
Her zamanki gibi, bu modülün içeriğini şu şekilde görüyoruz:
>>> import sys
>>> dir(sys)
Bu çıktıdaki öğeler, kullandığınız işletim sistemine göre farklılık gösterebilir. Örneğin winver adlı nitelik sadece Windows’ta çalışacaktır...
Bu bölümde sys modülünün içindeki fonksiyon ve niteliklerden en önemli olanlarını işlemeye çalışacağız. Burada işleyeceğimiz nitelik ve fonksiyonlar şunlardır:
- sys.argv
- sys.executable
- sys.exit
- sys.getdefaultencoding
- sys.path
- sys.platform
O halde dilerseniz vakit kaybetmeden ilk öğemizle işe koyulalım...
11.2.2.1. argv Niteliği¶
Bu nitelik sys modülünün en fazla kullanılan öğelerinden bir tanesidir. argv yapı olarak aslında basit bir listeden ibarettir. Python’u normal bir şekilde başlatıp etkileşimli kabukta şu komutu verecek olursak alacağımız çıktı içi boş bir karakter dizisi içeren tek öğeli bir liste olacaktır:
>>> sys.argv
['']
>>> len(sys.argv)
1
Gördüğünüz gibi, elimizdeki şey bir listeden ibarettir... Peki bu sys.argv denen şey ne işe yarar?
sys.argv bize Python’un hangi parametrelerle başlatıldığını gösterir. Dilerseniz bunu basitçe test edelim. Şimdi bir Python dosyasına şu kodları yazalım:
import sys
print(sys.argv)
Daha sonra bu dosyayı mesela “deneme.py” adıyla kaydedelim ve komut satırına gidip bu programı çalıştıralım:
python3 deneme.py
['deneme.py']
Buradan gördüğümüze göre python3 uygulaması “deneme.py” adlı parametre ile çalıştırılmış...
Dediğimiz gibi, sys.argv bir listedir. Dolayısıyla bu listenin öğelerine rahatlıkla erişebilirsiniz:
print(sys.argv[0])
deneme.py
Peki sys.argv‘nin bize verdiği bu bilgi neye yarar?
sys.argv‘den elde ettiğimiz çıktıyı kullanarak programımızla ilgili bazı önemli işlevleri yerine getirebiliriz. Mesela yukarıdaki örneği şöyle çalıştırmayı deneyelim:
python3 deneme.py --yardım
['deneme.py', '--yardım']
Bu defa sys.argv çıktısı iki öğeli bir liste verdi. İşte bu listeyi kullanarak mesela şöyle bir şey yazabilirsiniz:
import sys
if "--yardım" in sys.argv:
print("""
Yardım bölümüne hoşgeldiniz. Burada programın nasıl kullanılacağına
ilişkin kısa bilgiler bulacaksınız.""")
Eğer kullanıcımız yazdığımız programı “–yardım” parametresiyle birlikte çağırırsa, kendisine programımıza ilişkin yardım bilgileri sunuyoruz:
python3 deneme.py --yardım
Bu komut şöyle bir çıktı verecektir:
Yardım bölümüne hoşgeldiniz. Burada programın nasıl kullanılacağına
ilişkin kısa bilgiler bulacaksınız.
sys.argv‘yi kullanarak, programınızın parametreli mi yoksa parametresiz mi çalıştırıldığını denetlemek için sys.argv‘nin uzunluğunu kontrol edebilirsiniz:
import sys
if len(sys.argv) < 2:
print("programımızı parametresiz olarak çalıştırdınız!")
else:
print("programımızı parametreli olarak çalıştırdınız!")
Eğer sys.argv adlı listenin uzunluğu 2’den azsa program parametresiz çalıştırılmış demektir. Eğer uzunluk 2 ya da daha fazla ise kullanıcımız programımıza en az bir adet parametre eklemiş demektir...
11.2.2.2. executable, getdefaultencoding ve platform¶
Bu bölümde üç minik nitelikten/fonksiyondan bahsedeceğiz. Bunlar sys.executable ve sys.platform" adlı nitelikler ile ``sys.getdefaultencoding() adlı fonksiyondur. Bu üç öğe bize sistem hakkında bazı bilgiler verir. Önce sys.executable niteliğinin ne verdiğine bakalım:
>>> sys.executable
Bu komut bize kullandığımız sisteme bağlı olarak, çalıştırılabilir Python dosyasının adını ve konumunu verecektir. Mesela GNU/Linux’ta bu komutun çıktısı “/usr/bin/python3” gibi bir şey olurken, Windows’ta “c:\python3x\python.exe” olacaktır...
sys.getdefaultencoding fonksiyonu ise Python’un varsayılan olarak hangi kodlama sistemini kullandığını gösterir:
>>> sys.getdefaultencoding()
Bu komut “utf-8” çıktısı verecektir. Python’un 2.x sürümlerinde bu komutun çıktısı “ascii” idi... Python’un 3.x sürümüyle birlikte gelen “utf-8” desteği sayesinde İngiliz alfabesinde bulunmayan harflerle de işlem yapabiliyoruz...
Son olarak sys.platform adlı niteliğin çıktısına bakacağız:
>>> sys.platform
Bu komut Windows’ta “win32” çıktısını verirken GNU/Linux’ta “linux2” çıktısını verecektir. Bu komutun çıktısı kullanılan sistemin özelliğine göre farklılık gösterebilir...
11.2.2.3. exit Fonksiyonu¶
“exit” kelimesi “çıkmak” anlamına geliyor. Adından da anlaşılacağı gibi, bu fonksiyon Python programından çıkmamızı sağlar. Bunu şu şekilde kullanıyoruz:
sys.exit()
Eğer yazdığımız bir programın herhangi bir aşamasında programı terketmemiz gerekirse sys.exit() fonksiyonundan yararlanabiliriz:
import sys
sayı = "23"
while True:
soru = input("Bir sayı tutun: ")
if soru == sayı:
sys.exit()
else:
continue
Burada eğer kullanıcının girdiği sayı 23’e eşitse programdan çıkılacaktır...
11.2.2.4. path Niteliği¶
Hatırlarsanız, önceki derslerimizde os.path adlı bir modülden söz etmiştik. Şimdi işleyeceğimiz sys.path modülünü daha önce işlediğimiz os.path modülüyle karıştırmamamız gerekiyor. İsim olarak birbirlerine benzeseler de bu iki öğenin görevleri birbirinden çok farklıdır.
sys modülünün path niteliği bize Python’un modülleri içe aktarma sistemiyle ilgili önemli bilgiler verir. Dilerseniz bu path niteliğini anlatmaya başlamadan önce biraz modül içe aktarma sisteminden söz edelim.
Python’da “import modül_adı” komutunu verdiğimizde, Python aradığımız modülü bulabilmek için sistem üzerinde birkaç farklı konuma bakar. Biz “import modül_adı” komutunu verdiğimizde Python’un ilk bakacağı yer o anda içinde bulunduğumuz dizindir. Yani Python öncelikle os.getcwd() ile elde edilen dizin adının içini kontrol edecektir. Eğer aradığımız modül bu dizin içinde yoksa, Python’un kendi içinde tanımlı olan özel dizinlerin içeriği kontrol edilecektir. Eğer aranan modül hiç bir yerde bulunamazsa Python bize bir hata mesajı gösterecektir. Python’un, bir modülü bulamaması durumunda verdiği hata şöyledir:
import falanca
ImportError: No module named falanca
Daha önce de sözünü ettiğimiz gibi, Python’un kendi içinde bulunan modüller haricinde bir de internet üzerinden veya başka kaynaklardan elde edilen modüller vardır. O modülleri kullanabilmek için öncelikle ilgili modülü bilgisayarımıza kurmamız gerekir. Dolayısıyla eğer isterseniz, o modülleri kullanarak yazdığınız programlarda şöyle bir kontrol kodu yazabilirsiniz:
try:
import falanca
except ImportError:
print("falanca adlı modül bilgisayarınızda kurulu değil.")
print("Bu modülü filanca adresinden indirebilirsiniz.")
Böylece harici bir modüle bağımlı olan programınız, son kullanıcı için anlamsız bir hata üretmek yerine, kullanıcıya daha makul bir mesaj gösterebilecektir...
Dedik ki, eğer aradığımız modül o anda çalıştığımız dizin içinde yoksa, Python kendi içinde tanımlı olan özel dizinlerin içeriğini kontrol edecektir... Peki bu dizinler hangileridir? İşte burada sys.path adlı nitelik devreye giriyor. Şimdi bu niteliğin çıktısına bakalım:
>>> sys.path
Bu komutun çıktısında görünen dizinler, o bahsettiğimiz özel dizinlerdir. Eğer o anki çalışma dizininde bulunamayan modül sys.path listesinden elde edilen çıktıdaki dizinlerde de yoksa, yukarıda bahsettiğimiz “ImportError” adlı hata verilecektir...
Dediğimiz gibi, sys.path aslında bir listeden ibarettir. Dolaysıyla listelerin bütün metotlarını destekler. Mesela listelerin append adlı metodunu kullanarak, herhangi bir dizini bu listeye ekleyebilirsiniz:
>>> sys.path.append("/falanca/filanca/")
Elbette bu değişiklik kalıcı olmayacaktır. Programınızı veya etkileşimli kabuğu kapattığınızda sys.path listesi özgün haline geri dönecektir.
11.3. Kendi Modüllerimizi Yazmak¶
Şimdiye kadar hep halihazırda yazılmış olan modülleri kullanmayı öğrendik. Bu bölümde ise modüllerimizi kendimiz yazmayı ve kullanmayı öğreneceğiz.
En başta da dediğimiz gibi, sonu ”.py” uzantısı ile biten bütün dosyalar aslında bir modüldür ve başka programların içine aktarılabilme potansiyeli taşırlar. Bununla ilgili çok basit bir örnek verelim. Diyelim ki elimizde şöyle bir kod var:
isim = "istihza"
eposta = "kistihza[at]yahoo[nokta]com"
Yine diyelim ki bu kodlar “bilgi.py” adlı bir dosya içinde bulunuyor. İşte bu “bilgi.py” adlı dosya bir modüldür ve bu modülün adı da bilgi‘dir... Dolayısıyla bu modülü başka bir program içinden çağırabiliriz.
Şimdi mesela “bilgi.py”nin olduğu klasör içinde “deneme.py” adlı başka bir dosya daha oluşturup içine şunu yazalım:
import bilgi
Geçen bölümlerde sys.path konusunu anlatırken, Python’un bir modülü bulmak için hangi dizinlere baktığını söylemiştik. Orada da dediğimiz gibi, Python aradığımız bir modülü bulabilmek için önce o anda çalışılan dizinin içine ardından da sys.path içinde görünen dizinlere bakar. Eğer aradığımız modül bu dizinlerin hiçbirinde bulunamazsa, Python bize bir hata mesajı gösterir. Dolayısıyla kendi yazdığımız modülleri pratik şekilde kullanabilmek için en makul yol, modüllerimizi ve bu modülleri çağırmak için kullandığımız ana programımızı aynı klasör içine yerleştirmektir. Yani bu “bilgi.py” adlı dosyayı ve bu modülü içe aktarmak için kullandığımız “deneme.py” adlı dosyayı aynı dizin içine koyarsak, bilgi adlı modülü içe aktarmak kolay olacaktır...
Yukarıda gösterdiğimiz “import bilgi” komutunu verdikten sonra “bilgi.py” içindeki bütün nitelikleri “deneme.py” adlı dosyanın içine aktarmış oluyoruz. Artık bilgi adlı modülün bize sunduğu bütün olanaklardan yararlanabiliriz. Mesela bilgi.py içindeki isim adlı niteliğe erişmek için şöyle bir şey yazabiliriz:
import bilgi
print(bilgi.isim)
Bu kodların çıktısı şu olacaktır:
istihza
Bu bilgi adlı modülü tıpkı daha önce öğrendiğimiz os ve sys modülleri gibi kullandığımıza dikkat edin. Mesela os modülü içindeki name adlı niteliğe erişmek için şöyle bir şey yazıyorduk:
import os
print(os.name)
Aynı şekilde bilgi modülü içindeki isim adlı niteliğe erişmek için de “bilgi.isim” komutunu veriyoruz..
Elbette modülümüzün içine fonksiyon da yazabiliriz. Mesela daha önceki derslerimizin birinde yazdığımız çarp() adlı fonksiyonu bu modül içine yerleştirelim:
isim = "istihza"
eposta = "kistihza[at]yahoo[nokta]com"
def çarp(liste):
a = 1
for i in liste:
a = i * a
print(a)
Artık bilgi adlı modülümüzün, isim ve eposta adlı niteliklerinin yanısıra, çarp adlı bir fonksiyonu da var... Bu fonksiyona şu şekilde erişebileceğimizi biliyorsunuz:
import bilgi
lis = [20, 45, 55]
bilgi.çarp(lis)
Burada önemli bir noktaya değinmemizde yarar var. Özellikle etkileşimli kabuk üzerinde çalışırken, içe aktarma konusunda Python’un bir özelliğine dikkat etmemiz gerekir. Python aynı oturum içinde bir modülü sadece bir kez içe aktarır. Yani biz etkileşimli kabukta “import modül_adı” komutunu ilk verişimizde modülümüz içe aktarılır. Bundan sonra vereceğimiz “import modül_adı” komutları hiç bir işe yaramaz. Bunu şöyle test edebiliriz. Diyelim ki “bilgi.py” adlı dosyamız masaüstünde kayıtlı. Şimdi etkileşimli kabuğu masaüstünün olduğu dizinde açıp şu komutları verelim:
>>> import bilgi
>>> dir(bilgi)
['__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'eposta', 'isim', 'çarp']
Gördüğünüz gibi, bizim tanımladığımız eposta, isim ve çarp öğeleri modülümüzün içinde görünüyor. Şimdi “bilgi.py” adlı dosyayı açıp içine şöyle bir ekleme yapalım:
telefon = "02121231212"
Yani dosyamızın son hali şöyle görünecek:
isim = "istihza"
eposta = "kistihza[at]yahoo[nokta]com"
telefon = "02121231212"
def çarp(liste):
a = 1
for i in liste:
a = i * a
return a
Şimdi etkileşimli kabukta bu modülün içeriğini tekrar kontrol edelim:
>>> dir(bilgi)
Gördüğünüz gibi, modüle yeni eklediğimiz telefon niteliği listede görünmüyor. Çünkü eklemeler modüle otomatik olarak kaydedilmiyor. Şimdi modülümüzü tekrar içe aktarmayı deneyelim:
>>> import bilgi
>>>dir(bilgi)
Listede yine herhangi bir değişiklik olmadığına dikkat edin. Zaten telefon niteliğini kullanamamamızdan da bellidir bu:
>>> bilgi.telefon
AttributeError: 'module' object has no attribute 'telefon'
Bu hata mesajı şöyle çevrilebilir: “NitelikHatası: “module” nesnesinin “telefon” adlı bir niteliği yok“
Halbuki biz bu modüle biraz önce telefon adlı bir nitelik eklemiştik...
Eğer bunun gibi durumlarda modülümüzü tekrar içe aktarmak istersek Python’daki imp adlı bir modülün reload adlı fonksiyonundan yararlanmamız gerekir:
>>> import imp
>>> imp.reload(bilgi)
Artık modülümüzün telefon adlı niteliğini kullanabiliriz:
>>> print(bilgi.telefon)
02121231212
Dolayısıyla modüllerimizi “tazeleme” ihtiyacı duyduğumuzda yardımımıza koşacak fonksiyon, imp modülünün reload fonksiyonudur...
11.4. if __name__ == “__main__”¶
Python’da, kendi yazdığınız modüller de dahil, dir() fonksiyonunu kullanarak hangi modülün içine bakarsanız bakın orada __name__ adlı bir nitelik görürsünüz. “name” kelimesi Türkçe’de “isim” anlamına geliyor. Bu fonksiyon bize modülün adının ne olduğunu söylemekle yükümlüdür.
Bir modülün farklı durumlara göre iki adı bulunur: “__main__” veya modülün kendi adı... Hemen bir örnek verelim... Şimdi boş bir dosyaya şu satırı yazıp “isim.py” adıyla kaydedelim:
print(__name__)
Daha sonra başka bir boş dosyaya şu satırı yazıp “test.py” adıyla kaydedelim:
import isim
Şimdi komut satırında şu komutu verelim:
python3 isim.py
Bu komutun çıktısı “__main__” olacaktır. Şimdi de şuna bakalım:
python3 test.py
Bu komut ise “isim” çıktısını verecektir...
Buradan şu sonuçları çıkarıyoruz:
- Eğer bir modül doğrudan çalıştırılırsa __name__ niteliği (yani ismi) “__main__” oluyor.
- Eğer bir modül doğrudan değil de bir başka program içinden çağrılıyorsa __name__ niteliği modülün kendi adı oluyor.
Yukarıdaki örnekte, “python3 isim.py” komutunu vererek isim adlı modülü doğrudan çalıştırmış olduk. Dolayısıyla __name__ niteliğinin değeri “__main__” oldu. “python3 test.py” komutunu verdiğimizde ise isim adlı modülü test.py adlı program içinden çağırmış olduk. Bu yüzden de __name__ niteliğinin değeri modülün kendi adı olan “isim” oldu...
Peki bu özellik ne işimize yarar?
Python’da __name__ niteliğinin değerini kontrol ederek, yazdığınız modülleri test edebilirsiniz. Mesela bir önceki bölümde verdiğimiz örneği ele alalım:
isim = "istihza"
eposta = "kistihza[at]yahoo[nokta]com"
telefon = "02121231212"
def carp(liste):
a = 1
for i in liste:
a = i * a
return a
Bu modül bu haliyle doğrudan çalıştırıldığı zaman herhangi bir çıktı vermez (dosya adının “deneme.py” olduğunu varsayıyoruz):
python3 deneme.py
Şimdi bu dosyaya şöyle bir ekleme yapalım:
if __name__ == "__main__":
lis = [2, 3, 4]
print("deneme amaçlı hesap işleminin sonucu: ", carp(lis))
Yani programımızın en son hali şöyle görünecek:
isim = "istihza"
eposta = "kistihza[at]yahoo[nokta]com"
telefon = "02121231212"
def carp(liste):
a = 1
for i in liste:
a = i * a
return a
print(__name__)
if __name__ == "__main__":
lis = [2, 3, 4]
print("deneme amaçlı hesap işleminin sonucu: ", carp(lis))
Komut satırında “python3 deneme.py” komutunu verdiğimizde şu çıktıyı elde ederiz:
deneme amaçlı hesap işleminin sonucu: 24
Böylece yazdığımız modülün çalışıp çalışmadığını ufak bir kod parçasıyla test etmiş olduk. Artık bu modülü güvenle başka programlar içinden çağırabiliriz. Mesela “test.py” adlı bir dosya oluşturup şu kodları yazmayı deneyelim:
import deneme
lst = [20, 10, 30]
print("test.py modülünden çağrılarak yapılan hesap işleminin sonucu: ", deneme.carp(lst))
Komut satırında “python3 test.py” komutunu verdiğimizde ise şu sonucu elde edeceğiz:
test.py modülünden çağrılarak yapılan hesap işleminin sonucu: 6000
Burada durumu birazcık daha somutlaştırmak için modül içine şu satırı ekleyerek arka planda neler olup bittiğini görebilirsiniz:
print("'__name__' niteliğinin değeri: ", __name__)
Şöyle:
isim = "istihza"
eposta = "kistihza[at]yahoo[nokta]com"
telefon = "02121231212"
def carp(liste):
a = 1
for i in liste:
a = i * a
return a
print("'__name__' niteliğinin değeri: ", __name__)
if __name__ == "__main__":
lis = [2, 3, 4]
print("deneme amaçlı hesap işleminin sonucu: ", carp(lis))
Burada modülü ne şekilde çalıştırdığımıza bağlı olarak __name__ niteliğinin değerinin nasıl değiştiğine dikkat edin...