30 Temmuz 2013 Salı

sys Modülü

sys modülü Python sistemine ilişkin fonksiyonlar ve nitelikler barındırır. Yani bu modül sayesinde kullandığımız Python sürümünü yönetebiliriz.
Modüller konusunu incelerken Python da bulunan modüllerin aslında birer Python programı olduğunu söylemiştik. Yani os modülü aslında os.py adında bir programdır. Ama bunların bazı istisnaları vardır. sys modülü de bunlardan biridir.sys modülü Python programlama dili ile değilde C programlama dili ile yazılmıştır.
Diğer her şeyde olduğu gibi sys modülünün içeriğini öğrenmek için dir() fonksiyonunu kullanabiliriz.
import sys
print dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__stderr__', '__stdin__', 
'__stdout__', '_clear_type_cache', '_current_frames', '_getframe', '_mercurial', 'api_version', 'argv', 
'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode','exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable',
'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding',
'getdlopenflags', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof',
'gettrace', 'hexversion', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 
'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'py3kwarning', 'pydebug', 'setcheckinterval', 
'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 
'version', 'version_info', 'warnoptions']
Gördüğünüz gibi sys modülü içerisinde bir hayli fonksiyon ve nitelik barındırıyor. Biz bunlardan bazılarını inceleyeceğiz.
argv Niteliği
Python programını komut satırında çalıştırırken gönderdiğimiz argümanlar argv Niteliği'ne eleman olarak gönderilirler. Şimdi argv.py adında bir program oluşturun ve içerisine şu kodları yazın.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
print sys.argv[1]
Şimdi bu programı komut satırında şu şekilde çalıştırın.
python argv.py test
test
Gördüğünüz gibi ekrana test ifadesini yazdı. İşte argv niteliği komut satırında çalışırken yanında ek olarak argüman almamızı sağlar. Birden fazla argüman da gönderebiliriz.
import sys
print sys.argv[2]
Şimdi ikinci bir argüman gönderelim.
python argv.py test deneme
deneme
argv niteliğini tam anlayabilmek için programımızı şu hale getirelim.
import sys

print sys.argv
Aynı şekilde komut satırında çalışalım ve aldığımız çıktıya bir bakalım.
python argv.py test deneme
['argv.py', 'test', 'deneme']
Gördüğünüz gibi çıktı olarak bir liste elde ettik. Bu listedeki ilk elemanın programımızın adı olduğunu fark etmişsinizdir. Listeler üzerinde yaptığımız tüm işlemleri bu liste üzerinde de yapabiliriz. Şimdi bir tane ac.py adında bir dosya oluşturun ve içerisine şu kodları yazın.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os

def ac():
    if os.name == "nt":
        os.startfile(sys.argv[1]) #Eğer işletim sistemi windows ise
    elif os.name == "posix":
        os.system("xdg-open %s" %sys.argv[1]) #Eğer işletim sistemi Lünux ise

if(len(sys.argv)>2)
    print "Birden fazla dosyayı açmaya çalıştınız."
else:
    ac()

Gördüğünüz gibi kullanıcıdan programı komut satırında çalıştırırken, açmak istediği dosyanın adını da argüman olarak istiyoruz. Girdiği programı os modülünde işlediğimiz nitelikler ile işletim sistemine göre açıyoruz. Burada gönderilen argümanları sayarken 2 sayısını kullandığımıza dikkat edin. Hatırlarsanız argv niteliğinin tuttuğu listenin ilk elemanı programın kendi adıydı. Bu yüzden bu listenin eleman sayısı zaten en az birdir.
exit() Fonksiyonu
exit() Fonksiyonu programın sonlanmasını sağlar.
import sys

isim = raw_input("Öğrenim:").lower()
if isim == "üniversite":
    print "Hoşgeldiniz."
else:
    print "Bu program size uygun değil,sonlandırılıyor."
    sys.exit()

print "Program sonlanırsa bu yaazıyı kullanıcı göremez."
Öğrenim:ilköğretim
Bu program size uygun değil,sonlandırılıyor.
Gördüğünüz gibi eğer kullanıcı üniversite öğrenimi görmüyorsa program sonlanır. exit() fonksiyonunun yaptığı ekstra bir işlem yoktur.
getdefaultencoding() Fonksiyonu
Python 2.x programları yazarken bildiğiniz gibi her programımızın başına şu kodu yazıyoruz.
# -*- coding: utf-8 -*-
Bu kodu yazmadan şu şekilde bir program yazmaya çalışalım.
print "Bu yazı Türkçe karakterler bulundurmaktadır."
SyntaxError: Non-ASCII character '\xc4' in file /home/mazlumagar/workspace/Python/sys/getdefaultencoding.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
Gördüğünüz gibi Python, ASCII karakterlerinden farklı karakterler kullanıldığı için, bu karakterleri tanımadı ve hata döndürdü. Şimdi getdefaultencoding() fonksiyonunun ne işe yaradığına bakalım.
import sys
print sys.getdefaulteimncoding()
ascii
Gördüğünüz gibi getdefaultencoding() Python'daki ön tanımlı kodlama biçimini gösteriyor. Python 2.x sürümlerinde ön tanımlı kodlama biçimi ascii olduğu için Türkçe karakter problemi yaşıyoruz. Bu problemin üstesinden gelebilmek için de yukarıda gösterdiğimiz kod parçasını programımıza ekleyerek, kodlama biçimini UTF-8 çeviriyoruz.
Aynı programı Python 3.x sürümünde çalıştıralım.
utf-8
Gördüğünüz gibi Python 3.x sürümünde ön tanımlı kodlama biçimi olarak UTF-8 geliyor. Bu yüzden Python 2.x'de yaşadığımız Türkçe karakter problemini 3.x sürümlerinde yaşamıyoruz.
path Niteliği
Python bir modolü içe aktarırken Python bu modülü path Niteliği'nin gösterdiği dizinler içerisinde arar.
import sys
for i in sys.path:
    print i
/home/mazlumagar/workspace/Python/sys
/home/mazlumagar/workspace/Python
/usr/lib/python2.7
/usr/lib/python2.7/plat-linux2
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages/PIL
/usr/lib/python2.7/dist-packages/gst-0.10
/usr/lib/python2.7/dist-packages/gtk-2.0
/usr/lib/python2.7/dist-packages/ubuntu-sso-client
/usr/lib/pymodules/python2.7
Gördüğünüz gibi Python'ın modülleri nerede aradığını listelemiş olduk. path Niteliği geriye bir liste döndürür. Listeler üzerinde yaptığımız ekleme,çıkarma gibi işlemleri bu liste üzerinde de yapabiliriz.
sys.path.append('/dizin/altdizin')
Python artık içe modül aktarırken bizim eklediğimiz dizin içerisine de bakacaktır. Bilmeliyiz ki program sonlandıktan sonra liste eski haline geri döner. Eklediğimiz dizinler sadece çalıştığımız program için geçerlidir.
Python bir modülü ararken bulma işlemini gerçekleştirdikten sonra arama işlemini sonlandırır. Yani bir modül iki dizinde birden varsa listenin ilk sırasında bulunan dizindeki modül içe aktarılacaktır.
platform Niteliği
Daha önce os Modülünü işlerken, kullanılan işletim sistemini tespit edebilmek için name niteliğini kullanabildiğimizi söylemiştik. sys Modülünün platform niteliği de aynı işlemi yapmaktadır.
import sys
print sys.platform
Linux 2
Linux üzerinde çalıştırdığımız için çıktı bu şekilde olacaktır.
İşletim Sistemi Çıktı
Linux Linux2
Windows win32
Mac OS darwin
sys modülünün platform niteliği bize kullandığımız işletim sisteminin kaç bit olduğu hakkında bilgi vermez. Windows'ta çıktının win32 olduğu sizi yanıltmasın. 64 bit Windows'ta da aynı çıktıyı verecektir. Eğer kullanılan işletim sisteminin kaç bit olduğunu öğrenmek istersek platform modülünden faydalanabiliriz.
import platform
print platform.architecture()
('32bit', 'ELF')
Gördüğünüz gibi 32 bit Linux işletim sisteminde çalıştığımız için bu şekilde çıktı aldık. Çıktının sözlük olduğuna dikkat edin. Sözlükler üzerinde yaptığımız işlemleri çıktı üzerinde yapabiliriz.
İşletim Sistemi Çıktı
32 bit Linux ('32bit', 'ELF')
64 bit Linux ('64bit', 'ELF')
32 bit Windows ('32bit', 'WindowsPE')
64 bit Windows ('64bit', 'WindowsPE')
stdout Niteliği
Bugüne kadar ekrana yazdırma işlemi yaparken print deyiminden faydalandık. Python, print deyimi ile yazdırdıktan sonra otomatik olarak yeni satıra geçer.
i=1
while i<10:
    print i
    i=i+1
1
2
3
4
5
6
7
8
9
Aynı işlemi for döngüsü ile de yapabiliriz. Burada bir alt satıra geçmesini istemezsek print deyiminden sonra virgül kullanabiliriz.
i=1
while i<10:
    print i,
    i=i+1
1 2 3 4 5 6 7 8 9
Gördüğünüz gibi bu sefer sayılar yan yana yazıldı. Ama bu sefer de aralarında birer boşluk bırakıldı. Eğer print deyiminden sonra virgül kullanılırsa ifadeler arasında birer boşluk bırakılır. İstediğimiz şey bu olmayabilir. Biz sadece ifadelerin yan yana yazılmasını istiyor olabiliriz. Eğer böyle bir şey istersek sys modülünün stdout niteliğinin write() fonksiyonunu kullanabiliriz.
import sys
i=1
while i<10:
    sys.stdout.write(str(i))
    i=i+1
123456789
İfadeler yan yana ve istediğimiz şekilde yazıldı. write() fonksiyonuna verdiğimiz argüman karakter dizisi olmak zorundadır.
sys.stdout.write(2)
Traceback (most recent call last):
    sys.stdout.write(2)
TypeError: expected a character buffer object
Sayı yazdırmaya çalışınca program hata verdi. Bu hatayı almamak için önceki örnekte ifadeleri karakter dizisine dönüştüren str() fonksiyonunu kullandık.
Biz şimdiye kadar print deyimi ile çıktıları ekrana verdik. Ama istersek bunu değiştirebiliriz. stdout niteliğini kullanarak print deyiminin nereye çıktı vereceğini belirtebiliriz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys

ac = open("stdout.txt","w")

sys.stdout = ac
print "print deyimi ile txt dosyasına yazıyoruz."
ac.close()
Burada kullandığımız sys.stdout=ac ifadesi ile print deyiminin çıktıları açtığımız dosyaya vereceğini söylüyoruz. Buradan anlıyoruz ki print deyimi varsayılan olarak çıktıları ekrana veriyor. Biz burada bunu değiştirdik. Eğer dosyayı kapattıktan sonra print ile yazmak istersek hata alırız.
print "deneme"
Traceback (most recent call last):
    print "deneme"
ValueError: I/O operation on closed file
Çünkü print deyimi burada açtığımız dosyayı arıyor. Biz dosyayı kapattığımız için hata ile karşılaşıyoruz. Peki print deyiminin tekrardan ekrana yazmasını nasıl sağlayacağız? Bunun için şu komutu kullanmamız yeterli.
sys.stdout = sys.__stdout__
print "deneme"
deneme
Artık sıkıntı olmadan ekrana çıktı verebildik. sys.__stdout__ ifadesi Python'ın öntanımlı standart çıktı komutunu tutar. Yani aslında programın kendi içinde sys.stdout ifadesi sys.__stdout__ değerine eşittir.
Geliştiricilerin tavsiye etiği yol ise şu şekildedir.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys

varsayilan = sys.stdout
ac = open("stdout.txt","w")

sys.stdout = ac
print "print deyimi ile txt dosyasına yazıyoruz."
ac.close()

sys.stdout = varsayilan
print "deneme"
deneme
Bu yöntem ile herhangi bir sıkıntı olmadan ilk önce açtığımız dosyaya sonrada ekrana yazı yazdırdık.
version_info Niteliği
version_info niteliği kullanılan Python sürümü hakkında bilgi verir.
import sys
print sys.version_info
sys.version_info(major=2, minor=7, micro=3, releaselevel='final', serial=0)

27 Temmuz 2013 Cumartesi

OS Modülü

Python bir çok modülden oluşur. Bir programcı ihtiyaç duyacağı hemen her temel fonksiyonu hazır modüller içerisinde bulabilir. os modülü işletim sistemi tarafından sağlanan bir çok hizmeti Python içerisinde kolay bir şekilde kullanmamızı sağlayacak nesneleri barındırır. Daha önce de söylediğimiz gibi .py uzantılı her dosya bir modüldür. Buradan anlıyoruz ki os modülü os.py programından başka bir şey değildir. Bizim yazdığımız modüllerden içeriği dışından hiç bir fark yoktur. GNU/Linux sistemlerinde bu modülü /usr/lib/python2.7/ dizininde Winodws sistemlerinde ise C:/Python26/Lib dizininde bulabilirsiniz.
Bu modülü kendi yazdığımız modüller gibi içe aktarıyoruz.
import os
Bu tarz Python ile beraber gelen modüllerin bizim yazdığımız modüllerden en önemli farkı, yazdığımız program nerede olursa olsun bu modülleri bu şekilde içe aktarabiliyoruz. Kendi yazdığımız modüllerde modül ve program yan yana olmalıydı. Bu modüller için ise bu gerekli değildir.
Şimdi gelin daha önce bahsettiğimiz dir() fonksiyonu ile os modülü içerisindeki fonksiyonları ve nitelikleri öğrenelim.
import os
for i in dir(os):
    print i
Bu kod parçasını çalıştırırsanız göreceksiniz ki os modülü içerisinde oldukça fazla fonksiyon ve işlev bulunmaktadır. Fazla olduğundan dolayı buraya yazmıyoruz. Şimdi en çok kullanılanlarını inceleyeceğiz.
os.name
Bu nitelik, kullandığımız işletim sistemi hakkında bilgi verir.
print os.name
posix
Biz GNU/Linux işletim sistemi üzerinde çalıştırdığımız için çıktı olarak posix verdi. İşletim sistemlerine göre çıktı şu şekilde olacaktır.
  • GNU/Linux için:“posix”
  • Windows için:“nt”, “dos”, “ce”
  • Macintosh için: “mac”
  • OS/2 için:“os2”
  • Risc Os için:“riscos”
os modülünün name niteliğini kullanarak işletim sistemlerine göre programlar yazabiliriz. Bu şekilde yazdığımız programın birden fazla işletim sistemi üzerinde çalışmasını sağlamış olur ve eğer işletim sistemi komutlarını kullanacaksak hataların önüne geçmiş oluruz.
Basit bir örnek yapalım;
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import os
if os.name=="posix":
    print "Özgür yazılıma destek verdiğiniz için teşekkür ederiz."
elif os.name=="nt":
    print "Bir an önce Özgür yazılıma geçiş yapmalısınız."
Özgür yazılıma destek verdiğiniz için teşekkür ederiz.
Not: Eğer kullandığınız işletim sistemi GNU/Linux tipinde ise os.uname ile çekirdeğe ait daha ayrıntılı bilgi elde edebilirsiniz.
print os.uname()
('Linux', 'mazlumagar-Ideapad-Z570', '3.2.0-41-generic-pae', '#66-Ubuntu SMP Thu Apr 25 03:50:20 UTC 2013', 'i686')
os.system()
Bu fonksiyon işletim sistemi ait sistem komutlarını çalıştırmamızı sağlar.
Sistem komutu: Üzerinde çalıştığımız işletim sitemine ilişkin işlemleri yerine getirmemizi sağlayan komutlardır. Örneğin; mkdir komutu Linux işletim sisteminde klasör oluşturmamızı sağlar.
import os
if os.system("mkdir 'Yeni Klasör'"):
    print "Klasör başarılı bir şekilde oluşturuldu."
else:
    print "Klasör oluşturulamadı."
Klasör başarılı bir şekilde oluşturuldu.
Gördüğünüz gibi os.system() fonksiyonun kullanımı oldukça basit. Burada "Yeni Klasör" adında bir dizin oluşturduk. Yapmamız gereken sadece system("sistem komutu") şeklinde kullanmaktır.
import os
if os.name=="posix":
    if os.system("mkdir 'Yeni Klasör'"):
        print "Klasör başarılı bir şekilde oluşturuldu."
    else:
        print "Klasör oluşturulamadı."
elif os.name=="nt":
    if os.system("md Yeni Klasör"):
        print "Klasör başarılı bir şekilde oluşturuldu."
    else:
        print "Klasör oluşturulamadı."
Klasör başarılı bir şekilde oluşturuldu.
Örneği biraz daha değiştirdik. Bir önceki başlıkta işlediğimiz os.name komutunu da kullanarak işletim sistemine göre işleyen bir program yazdık. Windows işletim sisteminde yeni klasör oluşturmaya yarayan sistem komutu md'dir.
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import os
os.system("xdg-open yazi.txt")
xdg-open komutu GNU/Linux işletim sistemlerinde çalışan bir komuttur. Bu komut istenilen dosya veya klasörü varsayılan uygulama ile açmamızı sağlar. Bu işlemi şu şekilde de yapabilirdik.
os.system("kwrite yazi.txt")
Burada varsayılan uygulama ile aç değilde "kwrite" uygulaması ile aç dedik. Bu tarz kullanım eğer sistem de "kwrite" yok ise hata verecektir. Bu yüzden xdg-open komutu bizim çok işimize yarayan bir komuttur. Windows'ta bu komuta benzer işlemi os.startfile("dosyaadi") ile yapabilirsiniz.
os.listdir()
os.listdir() fonksiyonu bir klasördeki klasör ve dosyaların listesini almamızı sağlar.
import os
print os.listdir(".")
['faktoriyel.py', 'listdir.py', 'os.uname.py', 'ilkmodul.py', 'yazi.txt~', 'faktoriyel.pyc', 'syste2.py', 'yazi.txt', 'environ.py', 'ilkmodul.pyc', 'system.py', 'modulcagir.py', 'Yeni Klas\xc3\xb6r', 'deneme.py']
Gördüğünüz gibi bize içinde bulunduğumuz dizinin içinde bulunan dosya ve klasör isimlerini bir liste şeklinde döndürdü. Burada kullandığımız "." içinde bulunduğumuz dizini temsil eder. Eğer bir üst dizine çıkmak istersek ".." kullanabiliriz. Burada tabi şu şekilde bir yolda belirtebiliriz; os.listdir("/usr/bin").
import os
for i,k in enumerate(os.listdir(".")):
    print i+1,k
1 faktoriyel.py
2 listdir.py
3 path.py
4 os.uname.py
5 ilkmodul.py
6 yazi.txt~
7 faktoriyel.pyc
Bu şekilde yazdığımız programı daha düzenli hale getirdik.
os.path()
Python'da klasörlere ilişkin fonksiyonları os modülünün path nesnesinde bulabilirsiniz. Bir patikanın(dosya veya klasör) var olup olmadığını os.path.exists() fonksiyonu ile kontrol edebiliriz.
os.path.exists('dosya veya klasör adı')
True
Eğer dosya veya klasör var ise "True" değer döner. os.path.exists() sadece dosya veya klasörün var olup olmadığı ile ilgilenir. Yani dosya mı klasör mü ? Bununla ilgilenmez.
import os 
dosya_adi = raw_input('Okuyacağınız dosya adını girin:')

if not dosya_adi:
    print "Dosya adı girmediniz.."
else:
    if os.path.exists(dosya_adi):
        print open(dosya_adi).read()
    else:
        print 'Böyle bir dosya yok'
Okuyacağınız dosya adını girin:yazi.txt
www.pythondersleri.com => Python için Türkçe doküman sağlar.
Bu programda kullanıcıdan bir dosya adı aldık ve var ise dosyayı okuduk. Ama burada girilen isim eğer bir dizin adı olursa program okumaya çalışır ve hata ile karşılaşırız. Eğer bir patikanın dosya mı yoksa klasör mü olduğunu kontrol etmek istiyorsak os.path.isfile() ve os.path.isdir() fonksiyonlarını kullanabiliriz. os.path.isfile() fonksiyonu dosya olup olmadığını kontrol eder. Şimdi önceki örneğimizi şu şekilde değiştirelim.
import os 
dosya_adi = raw_input('Okuyacağınız dosya adını girin:')

if not dosya_adi:
    print "Dosya adı girmediniz.."
else:
    if os.path.isfile(dosya_adi):
            print open(dosya_adi).read()
    else:
        print 'Böyle bir dosya yok'
Okuyacağınız dosya adını girin:Yeni Klasör
Böyle bir dosya yok
Gördüğünüz gibi artık kullanıcı var olan bir klasör bile girse program hata ile karşılaşmayacak.
İşlev Görev Örnek
os.path.basename() Verilen patikanın en son bileşenini verir. os.path.basename('/usr/bin/python')
python
os.path.dirname() Bir dosyanın bulunduğu klasörü verir. os.path.dirname('/usr/bin/python')
/usr/bin
os.path.splitext() Bir dosyayı uzantısına göre ayırır. os.path.splitext('/usr/lib/python2.7/os.py')
('/usr/lib/python2.7/os', '.py')
os.path.join() Verilen argümanları bir patikaya dönüştürür. os.path.join('usr','lib','python2.7','os.py')
usr/lib/python2.7/os.py
os.path.abspath() Verilen patikanın tam yerini verir. os.path.abspath('/usr/lib/python2.7')
/usr/lib/python2.7
Şimdi os.listdir() başlığında verdiğimiz örneği şu şekilde değiştirelim.
import os
klasor = "." 
for i in os.listdir(klasor):
    dosya = os.path.join(klasor,i)
    if os.path.isdir(dosya):
        print 'Klasör => ',i
    elif os.path.isfile(dosya):
        print 'Dosya => ',i
Dosya =>  faktoriyel.py
Dosya =>  listdir.py
Dosya =>  environ.py
Klasör =>  Deneme
Dosya =>  modulcagir.py
Klasör =>  Yeni Klasör
os.walk()
Program içerisinde bir klasörün tüm alt klasörleri ile birlikte taranmasını sağlar. walk() iterasyon edilebilir bir nesnedir. İterasyon sonucunda 3 elemandan oluşan bir demet döner. İlk eleman bulunulan klasörü, ikinci eleman bu klasörde bulunan klasörlerin listesi, üçüncü eleman ise bu klasörde bulunan dosyaların bir listesidir.
import os

for i in os.walk("/home/mazlumagar/Filmler"):
    print i
('/home/mazlumagar/Filmler', ['Macera', 'Dram', 'Aksiyon', 'Romantik'], [])
('/home/mazlumagar/Filmler/Macera', [], [])
('/home/mazlumagar/Filmler/Dram', ['Khan'], ['Benioku.txt'])
('/home/mazlumagar/Filmler/Dram/Khan', [], [])
('/home/mazlumagar/Filmler/Aksiyon', ['Bruce'], ['BeniOku.txt'])
('/home/mazlumagar/Filmler/Aksiyon/Bruce', [], [])
('/home/mazlumagar/Filmler/Romantik', [], [])
Filmler klasörünün içeriğini listelemiş olduk. Filmler klasöründe dört adet klasör var ve dosya yok. Dram klasöründe "Khan" adında başka bir klasör ve "Benioku.txt" adında dosya mevcut. walk() fonksiyonu bu şekilde bizim işimizi çok kolaylaştırarak klasörleri taramamızı sağlıyor.
os.access()
Sadece Unix tipi işletim sistemlerinde os.access() ile erişim denetimini kontrol edebiliriz. os.access() işlevine vereceğiniz ilk argüman patika ikinci argüman ise erişim kipidir.
Erişim Kipleri
  • os.F_OK:Patikanın var oluş kipi
  • os.R_OK:Okuma kipi
  • os.W_OK:Yazma kipi
  • os.X_OK:Tarama kipi
print os.access("/home/mazlumagar/workspace", os.R_OK)
True # workspace klasörünün okuma izni bulunmaktadır
print os.access("/usr", os.W_OK)
False # usr klasörünün yazma izni bulunmamaktadır.
Bu şekilde klasörlerin erişim izinlerini kontrol edebiliriz.
os.getcwd()
os.getcwd() fonksiyonu bize o an hangi klasör içinde çalıştığımızı döndürür.
import os 
print os.getcwd()

/home/mazlumagar/workspace/Python/mdül # Şuanda çalıştığımız dizinin yolu
os.chdir()
Bu fonksiyon sayesinde içinde bulunduğumuz dizini değiştirebiliriz. Hemen bir örnek verelim.
#-*- coding:utf-8 -*-
import os 

print "Dizin değiştirmeden önce=>",os.getcwd()
os.chdir('/var')
print "Dizin değiştirdikten sonra=>",os.getcwd()
Not:Daha önceki verdiğimiz örneklerde kullanmıştık. "." işareti içinde bulunduğumuz dizini temsil ediyordu. Python'da os.curdir de aynı işlevi görür. ".." işareti gibi os.pardir de bir üst dizini temsil eder. os.mkdir() ve os.makedirs()
os.mkdir() fonksiyonu klasör oluşturmamızı sağlar.
import os
os.mkdir("deneme")
Biz bu işlemi os.system("mkdir","yol") yönetimi ile de yapmıştık.
Peki iç içe birden fazla klasör oluşturmak istersek ne olacak? Bir deneyelim.
os.mkdir("deneme/test")
Traceback (most recent call last):
    os.mkdir("deneme/test")
OSError: [Errno 2] No such file or directory: 'deneme/test'
Burada içerisinde "test" adında bir klasör barındıran "deneme" klasörünü oluşturmaya çalıştık. Python bize hata döndürdü. Eğer bu şekilde iç içe klasörler oluşturmak istersek, os.mkdir() fonksiyonu bize yardımcı olamaz. Bunun için os.makedirs() fonksiyonunu kullanmalıyız.
import os
os.makedirs("deneme/test")
Bu şekilde herhangi bir hata almadan, klasörleri oluşturduk.
os.rmdir() ve os.removedirs()
Bu fonksiyonlar içi boş mevcut dizinleri silmemizi sağlar. Hemen bir örnek verelim. Çalışma dizinimiz içerisinde bulunan "test" isimli klasörü silelim.
import os

os.rmdir("test")
Başarılı bir şekilde silme işlemini gerçekleştirdik. Şimdi az önce oluşturduğumuz "deneme" klasörünü silmeye çalışalım.
os.rmdir("deneme")
Traceback (most recent call last):
    os.rmdir("deneme")
OSError: [Errno 39] Directory not empty: 'deneme'
Oluşturduğumuz "deneme" klasörü içerisinde "test" adında bir klasör bulundurduğu için Python bize hata döndürdü. Az önce de söylediğimiz gibi bu yöntemler boş klasörleri silmemizi sağlar. Klasör oluştururken geçerli kural burada da geçerlidir. Eğer iç içe birden fazla boş dizini silmek istersek os.removedirs() fonksiyonunu kullanmalıyız.
os.removedirs("deneme/test")
"deneme" ve içerisindeki "test" klasörlerini silmiş olduk.
sep Niteliği
Bu nitelik bize işletim sistemlerinin dizin ayraçları hakkında bilgi verir.
import os
print os.sep
/
Bu programı Linux'da çalıştırdığımız için bize "/" döndürdü. Yani Linux'da dizin ayracı olarak "/" kullanılıyor. Eğer bu programı Windows'da çalıştırırsanız şu çıktıyı alırsınız.
\\
Peki bu ne işimize yarar? Yazdığımız programın işletim sistemleri ayırt etmeden sorunsuz bir şekilde çalışmasını sağlar. Yani az önce klasör silerken dizin ayracını kendimiz yazdık. Ama aynı programı Windows'da çalıştırmak istersek sorun çıkartabilir. Bu yüzden şu şekilde kullanabiliriz.
os.rmdir("deneme"+os.sep+"test")
Bu şekilde "deneme" içersindeki "test" klasörünü silmiş olduk. Yada klasör oluştururken de aynı işlemi yapabiliriz.
import os

os.makedirs("deneme"+os.sep+"test")
Bu şekilde yazdığımız programın klasör oluşturması gerekebilir. Eğer biz direk kullandığımız işletim sisteminin dizin ayracını kullanırsak. Başka bir işletim sisteminde kullanan kullanıcı sorun ile karşılaşabilir. Bu yüzden doğrudan dizin ayracını kullanmak yerine os modülünün sep niteliğini kullanmak daha sağlıklı olacaktır.

25 Temmuz 2013 Perşembe

Modüller

Python modüler bir programlama dilidir. Peki burada modüler derken ne demek istiyoruz ? Python programlama dili parçalardan bütün elde etmek üzerine kurulmuş bir programlama dilidir. Bu parçalar istenildiği zaman bütüne dahil edilebilir. Böylelikle çalıştığımız ortamı sadece kullandığımız parçalardan oluşturarak gereksiz bellek tüketiminde bulunmamış oluruz.

Modülleri biraz daha açıklayarak beynimizde oturtalım. Bir programda aynı kodları tekrar tekrar yazmamak için Fonksiyonları kullanıyorduk. Tanımladığımız bir fonksiyon sadece o an içinde bulunduğumuz programda çalışır. Peki biz bu fonksiyonu başka bir program içinde çalıştırmak istersek ne yapmalıyız? Tabi ki kopyala yapıştır yapmayacağız. Programı içe aktarmamız (import) fonksiyonu kullanmak için yeterli olacaktır.
Python'da yazılmış her program aynı zamanda birer modüldür. Bu özellik sayesinde Python programlarında bulunan fonksiyon ve özellikler başka Python programlarında da rahatça kullanılabilirler.
Bu bölümde kendi modülümüzü yazmayı-Aslında daha önceden yazdığımız her program bir modül olduğu için bunu biliyoruz.Burada başka Python programında kullanımıyla ilgileneceğiz.-ve en çok kullanılan bazı hazır modüllerin kullanımından bahsedeceğiz.
Bir Modül Yazmak ve İçe Aktarmak
Daha önce söylediğimiz gibi yazdığımız her program aynı zamanda bir modüldür. Bir modül çeşitli değişkenlerin bulunduğu, fonksiyolar barındıran, bir veya daha fazla sınıfın bulunduğu karmaşık bir yapıya sahip olabilir.
Şimdi basit bir program(modül) oluşturalım ve "ilkmodul.py" adı ile kaydedelim.
#!/usr/bin/env python
#-*- coding:utf-8 -*-

program = "Python"
surum = "2.x"
Bu şekilde ilk modülümüzü oluşturmuş olduk. Bir modül çağrılırken sadece dosya adı kullanılır(uzantısı yazılmaz). Çağırma işlemi "import" ifadesi ile yapılır. Bildiğiniz gibi yukarıda ki programda değişkenleri şu şekilde kullanabiliyoruz.
print program
Python
Peki başka bir programda bu değişkeni kullanmak istersek ne yapmalıyız ? Şimdi "modulcagir.py" adında başka bir program oluşturalım. Bu iki programın aynı dizinde olmasına dikkat edelim.
import ilkmodul
print ilkmodul.program
Python
Gördüğünüz gibi ilk modülümüzü oluşturduk ve içindeki değişkeni başka bir programda kullandık. Şimdi bir fonksiyon bulunan modül tanımlayalım. İçinde Faktoriyel hesabı yapan bir fonksiyon bulunan "faktoriyel" adında şu şekilde bir modülümüz olsun.
#!/usr/bin/env python
#-*- coding:utf-8 -*-

def faktoriyel(sayi):
    fak = 1
    for i in range(sayi):
        fak= fak * (i+1)
    return fak
Bildiğiniz gibi biz bu program içinde istediğimiz yerde faktoriyel fonksiyonunu kulanabiliyoruz. Ama artık modüller sayesinde sadece bu program içinde değil istediğimiz herhangi bir program içerisinde kullanabileceğiz. Şimdi "hesapla.py" şeklinde bir program oluşturalım. Bu program içersinde faktoriyel fonksiyonunu kullanalım.
import faktoriyel
hesap = faktoriyel.faktoriyel(5)
print hesap
120
Bu şekilde faktoriyel modülü içerisinde bulunan her şeyi herhangi bir program içerisinde kullanabiliriz.
Modülleri İçe Aktarma Yöntemleri
Modülleri içe aktarmanın bir kaç yolu vardır. Biz sadece import modül_adi yöntemini öğrendik.
import modül_adi
Bu yöntem ile içeri aktarım yaptığımız zaman modül içerisinde bulunan her şeyi programımıza aktarmış oluyoruz. Verdiğimiz örneklerde kullandığımız gibi modül içerisinde bulunan değişken,fonksiyon veya herhangi bir şeyi kullanırken şu yönetimi kullanıyoruz.
modül_adi.fonksiyon_adi
Bu yöntem de doğrudan fonksiyon adını kullanırsak şu şekilde bir hata alırız.
print adi
Traceback (most recent call last):
  File  line 3, in 
    print adi
NameError: name 'adi' is not defined
from modül_adi import *
Daha öncede kullandığımız ilkmodul'u bu yöntem ile içe aktaralım.
from ilkmodul import *
print program
Gördüğünüz gibi sadece değişken adını yazarak kullanabildik. Burada kullandığımız * ifadesi içe aktardığımız modül içerisindeki tüm değerleri temsil etmektedir. Eğer biz sadece istediğimiz bir değişken veya fonksiyonu içe aktarmak istiyorsak, şu şekilde kullanabiliriz.
from ilkmodul import surum
print surum
Bu kullanım ile sadece surum değişkenini içe aktarmış olduk.
import modul_ismi as yeni_isim
Eğer içe aktaracağımız modülü kendi ismi ile değilde bizim belirlediğimiz isim ile çağırmak istersek bu şekilde takma bir isim verebiliriz.
import faktoriyel as fak
hesap = fak.faktoriyel(5)
print hesap
Gördüğünüz gibi artık faktoriyel modülünü fak ismi ile kullanıyoruz. Bu aktarım da eğer modülün kendi adını yazarak kullanmaya çalışırsanız hata alırsınız.
from modul_adi import nesne_adi as yeni_nesne_adi
import modul_ismi as yeni_isim kullanımında modüle takma isim veriyorduk. Bu kullanımda ise içe aktardığımız modül içersindeki bir nesneye takma isim veriyoruz. faktoriyel modülü içerisindeki faktoriyel fonksiyonunu şu şekilde içe aktaralım.
from faktoriyel import faktoriyel as fak
hesap = fak(5)
print hesap
Gördüğünüz gibi artık faktoriyel fonksiyonunu önünde modül adı olmadan ve yeni ismi ile kullandık.
Peki bu yöntemlerden hangisini kullanmalıyız? En güvenilir yöntem ilk(import modül_adi) bahsettiğimiz yöntemdir. Bu yöntem ile kullandığımız nesnelerin(örnek: modul.topla(10,5)) hangi modül içerisinde olduğunu rahat bir şekilde anlayabiliriz. İkinci(from modül_adi import *) kullanımında ise nesnenin(örnek: topla(10,5)) programın kendi içerisinde mi yoksa başka bir modülden mi içe aktarıldığını anlayamayız. Bu kullanımda eğer içe aktarılan modülde ve programda aynı isimde nesneler bulunuyorsa istemediğimiz sonuçlar ile karşılaşırız. Bu yüzden en güvenilir olan import modül_adi yöntemini kullanmak daha sağlıklıdır.
Modüllerin İçeriğini Öğrenme
Başkaları tarafından yazılmış olan bir modülü içe aktardığımız zaman modül içerisinde var olan nesneleri bilmeliyiz ki kullanabilelim. Bir modül içerisinde nelerin var olduğunu dir() fonksiyonu ile öğrenebiliriz.
import faktoriyel
print dir(faktoriyel)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'adi', 'faktoriyel']
Gördüğünüz gibi faktoriyel modülü içerisinde bulunan faktoriyel fonksiyonunu görebiliyoruz. Diğerleri tüm modüller için standart nesnelerdir. Bu şekilde içe aktaracağımız bir modül içeriğini öğrenebiliriz.

11 Temmuz 2013 Perşembe

Bu bölümde doğrudan düzenli ifadelerin değil, düzenli ifadeler ile oluşan eşleşme nesnelerinin metotlarını göreceğiz. Gelin ilk önce hangi metotlar var, onlara bir bakalım.
import re

karakter = "Python"

nesne = re.match("Python",karakter)
for i in dir(nesne):
    if not i.startswith("__"):
        print i
end
endpos
expand
group
groupdict
groups
lastgroup
lastindex
pos
re
regs
span
start
string
Gördüğünüz gibi oldukça metod var. Bunlardan bazılarını beraber inceleyeceğiz.
group() Metodu
Bu metodu daha önce de sık sık kullanmıştık. Hatırlarsınız ki group() metodu düzenli ifadeler ile eşleştirdiğimiz karakter dizilerini görmemizi sağlıyordu.
"()" metakarakterini kullanarak group() metodu ile ilgili bir kaç örnek verelim.
#-*-coding:utf-8-*-

import re

karakter = "Python programlama dilini öğreniyorum"

duzenli = re.search("(Python) (programlama) (dilini) (öğreniyorum)",karakter)
Bu örnekte "()" metakarakterini kullanarak birden çok eşleştirme yaptık. group() metodunu kullanarak bunları ekrana yazdırabiliriz.
print duzenli.group()
Python programlama dilini öğreniyorum

print duzenli.group(0)
Python programlama dilini öğreniyorum
Gördüğünüz gibi group() metodunu kullanarak yaptığımız eşleştirmelerin hepsini ekrana yazdırdık. Dikkatinizi çekmiş olmalı ki group(0) şeklinde kullanım da group() ile aynı sonucu verdi. Yani group(0) şeklinde kullanım da tüm eşleştirmeleri geriye döndürür.
print duzenli.group(1)
Python

print duzenli.group(2)
programlama
Kısacası group() metodu eşleştirmeleri gruplamamızı sağlıyor.
groups() Metodu
groups() metodu eşleştirme yaparken "()" metakarakterini kullanarak oluşturduğumuz bütün grupları demet olarak geriye döndürür.
print duzenli.groups()
karakter = "Python programlama dilini ogreniyorum"

duzenli = re.search("(Python) (programlama) (dilini) (ogreniyorum)",karakter)

('Python', 'programlama', 'dilini', 'ogreniyorum')
Gördüğünüz gibi groups() metodunu kullanarak oluşturduğumuz grupları demet şeklinde elde etmiş olduk. Demetlerin tüm özellikleri burada oluşturduğumuz demet içinde aynen geçerlidir.
if duzenli.groups().count("Python"):
    print "Yapılan gruplamada 'Python' ifadesi bulunmuştur."
Yapılan gruplamada 'Python' ifadesi bulunmuştur. 
Burada demetlerin "count" özelliğini kullanarak sorgulama işlemi yaptık.
Özel Diziler
Bu bölümde Python'da metakarakterler dışında düzenli ifadeler ile kullanılan bazı özel ifadelere değineceğiz.
Bu özel ifadeler:
\s => Boşluk karakterini yakalar.
\d => Ondalık sayıları yakalar.
\w => Alfanümerik karakterler ve "_" karakterini yakalar.
\s Özel Dizisi
import re

liste = ['Parker','Dünyalar Savaşı','Hangover','Hızli Ofkeli','Zor Olüm']

for i in liste:
    if re.search(u"[A-Za-z]+\s[A-Za-z]+",i):
        print i
Dünyalar Savaşı
Hizli Ofkeli
Zor Olüm
Bu örnekte büyük veya küçük harflerden oluşan, boşluk ile devam eden, ardından tekrar büyük veya küçük harflerden oluşan liste ögelerini ayıkladık. Yani iki kelimeli film isimlerini yakalamış olduk. Burada boşluk karakterini "/s" özel dizisi ile yakaladık.
\d Özel Dizisi
Bugüne kadar yaptığımız örneklerde ondalık sayıları kullanmak için [0-9] ifadesini kullandık. Aynı eşleştirmeyi "\d" özel dizisi ile de yapabilmekteyiz. Bir önceki örneğimizi şu şekilde değiştirelim.
liste = ['Parker','2 Guns','Hangover','300 Spartalı','Zor Olüm']

for i in liste:
    if re.search(u"\d+\s[A-Za-z]+",i):
        print i
2 Guns
300 Spartalı
Gördüğünüz gibi sayı ile başlayan filmleri bulmak için "\d" özel dizisini kullandık ve ardından boşluk ile devam etmesi için "\s" özel dizisini kullandık.
\w Özel Dizisi
ifade = "a21_?ab_%+"

print re.search("\w*",ifade).group()
a21_
Burada "\w" özel dizisini kullanarak alfanümerik karakterleri ve "_" karakterini yakalamış olduk. Bu özel dizi "[A-Za-z0-9_]" ifadesi ile aynı anlama gelmektedir. Gördüğünüz gibi işimizi ne kadar da kısaltmış oluyoruz.
Python'da bulunan bu özel dizilerin birde büyük harfli olanları vardır. Büyük harfli olanlar küçük harfli özel dizilerin yaptığı işin tam tersini yaparlar.

%S => Boşluk olmayan karakterleri yakalar.
%D => Ondalık sayı olmayan karakterleri yakalar.
%W => Alfanümerik olmayan ve "_" olmayan karakterleri yakalar.

Verdiğimiz örneklere göre bunlar da gayet net bir şekilde anlaşılıyor. Bu yüzden Ondalık dizilerin büyükleri için özel olarak örnek verilmeyecektir.
Düzenli İfadelerin Derlenmesi
compile() Metodu
Düzenli ifadeler karakter dizilerine göre daha yavaştırlar. Düzenli ifadelerin daha hazlı çalışmasını sağlamak için compile() metodu kullanılabilir. compile() metodu kullanılarak düzenli ifade kalıpları kullanılmadan önce derlenerek daha hızlı çalışırlar. Bu metot küçük boyutlu projelerde çok hissedilir bir fark yaratmasa da büyük boyutlu projeler için çok faydalı olacaktır.
import re

derle = re.compile("[A-Za-z]+\s[A-Za-z]+")
 
liste = ['Parker','Dünyalar Savaşı','Hangover','Hızli Ofkeli','Zor Olüm']

for i in liste:
    if derle.search(i):
        print i
Dünyalar Savaşı
Hızli Ofkeli
Zor Olüm
Özel dizileri kullanırken verdiğimiz örneği biraz değiştirerek tekrardan kullandık. Dikkat ederseniz düzenli ifade kalıbını compile() metodu içerisine yazarak ilk önce derleme işlemini yerine getirdik. search() metodunu kullanırken ise artık re.search() kalıbını değil de yeni oluşturduğumuz derle değişkenini kullanarak derle.search() ifadesini kullandık. derle.search() kalıbı içerisinde ise artık düzenli ifadeye yer vermedik, sadece karakter dizisini yazmış olmamamız yeterli oldu.
compile() ile Derleme Seçenekleri
compile() metodu ile derleme yapmayı gördük. Şimdi compile() ile bize sunulan bazı seçeneklere bakacağız. re.IGNORECASE veya re.I
Python programlama dili büyük küçük harflere duyarlıdır. Yani Python için "Python" ve "python" farklı karakter dizileridir. Eğer biz "Python" düzenli ifadesini bulmak istersek, bulduğumuz karakter dizileri arasında "python" karakter dizisini göremeyiz. İşte bu duyarlılığı ortadan kaldırmak için "re.IGNORECASE" veya "re.I" derleme seçeneklerini kullanabiliriz.
#-*-coding:utf8-*-

import re

metin ="""Bilgisayarlar çok farklı biçimlerde karşımıza çıkabilirler. 
20. yüzyılın ortalarındaki ilk bilgisayarlar büyük bir oda büyüklüğünde olup, 
günümüz bilgisayarlarından yüzlerce kat daha fazla güç tüketiyorlardı. 
21. yüzyılın başına varıldığında ise bilgisayarlar bir kol saatine sığacak ve 
küçük bir pil ile çalışacak duruma geldiler. Bu kadar küçük imal edilebilmelerinin 
temel nedeni 1969 yılında yarı iletkenler ile çok küçük alanlara sığdırılabilen 
devreler yapılabilmesidir. Şu anda kullandığımız bilgisayarlar Intel'in ilk işlemci
unvanına sahip olan 4004'den sonra bilgisayar teknolojisi hız kazanmıştır.
Toplumumuz kişisel bilgisayarı ve onun taşınabilir eşdeğeri,
dizüstü bilgisayarını, bilgi çağının simgeleri olarak tanıdılar ve 
bilgisayar kavramıyla özdeşleştirdiler. Günümüzde çok yaygın kullanılmaktadırlar. 
Bilgisayarın temel çalışma prensibi ikili sayı sistemi yani sadece 0 ve 1 den oluşan kodlamalardır."""

derle = re.compile("bilgisayar",re.I)
print derle.findall(metin)

['Bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'bilgisayar', 'Bilgisayar']
Gördüğünüz gibi elimizde bulunan bir metindeki "bilgisayar" kelimelerini büyük,küçük harf ayırt etmeden bulmuş olduk. Eğer re.I seçeneğini kullanmış olmasaydık, çıktı olarak sadece "bilgisayar" kelimesini alırdık. re.IGNORECASE de re.I seçeneği ile aynı işleve sahiptir.
re.DOTALL veya re.S
Metekarakterler arasında "." metakarakterini açıklaraken, yeni satır karakteri hariç herhangi bir karakterin yerini tuttuğunu söylemiştik.
#-*-coding:utf8-*-

import re

metin = "Python; \ngüçlü bir programlama dilidir"

print re.search("Python.*",metin).group()
Python;
Burada gördüğünüz gibi "." metakarakteri yeni satır(\n) karakterinin yerini tutmadığı için bize sadece "Python;" ifadesini geriye döndürdü. İşte biz "." metakarakterine bu özelliği de kazandırmak istersek re.DOTALL veya re.S özelliklerinden birini kullanabiliriz.
import re

metin = "Python;\ngüçlü bir programlama dilidir."
derle = re.compile("Python.*",re.DOTALL)

print derle.search(metin).group()
Python;
güçlü bir programlama dilidir.
Artık "." metakarakteri yeni satır karakterini de algıladı ve bize istediğimiz sonucu döndürdü. re.DOTALL seçeneği ile re.S seçeneği aynı işlevi yapmaktadır.
re.UNICODE veya re.U
Python'da düzenli ifadeleri kullanırken Türkçe karakter problemi ile karşılaşırız. Şu örneği inceleyelim;
#-*-coding:utf8-*-

import re

liste = ["otobüs","otomobil","kamyon","minibüs"]

for i in liste:
    print re.search("\w*",i).group()
otob
otomobil
kamyon
minib
Gördüğünüz gibi Python Türkçe karakterlerden sonraki karakterleri almadı. İşte bu tarz sorun yaşamamak için "re.UNICODE" seçeneğini kullanacağız. Bu kullanım GNU/Linux ve Windows için biraz farklılık gösterir.
GNU/Linux işletim sistemi için;
# -*- coding: utf-8 -*-

import re
import locale
locale.setlocale(locale.LC_ALL,"")

liste = ["otobüs","otomobil","kamyon","minibüs"]

for i in liste:
    liste[liste.index(i)] = unicode(i,"utf8")

derle = re.compile("\w*",re.UNICODE)

for i in liste:
    print derle.search(i).group()
otobüs
otomobil
kamyon
minibüs
Gördüğünüz çıktılarımızı herhangi bir sorun olmadan aldık. Burada "import locale" ifadesinden sonrasına dikkat edin. İlk önce bir döngü içinde tüm liste elemanlarını Unicode dönüştürdük. Eğer bu dönüştürme işlemini yapmazsak yine istediğimiz çıktıyı alamayız. Ve derleme işlemi yaparken Türkçe karakterlerde sorun çıkmaması için "re.UNICODE" seçeneğini kullandık. Bu şekilde herhangi bir sorun olmadan çıktılarımızı doğru bir şekilde almış olduk.
Windows kullanıcıları için;
#-*-coding:cp1254-*-

import locale
locale.setlocale(locale.LC_ALL,"")

import re

liste = ["otobüs","otomobil","kamyon","minibüs"]

derle = re.compile("\w*",re.UNICODE)

for i in liste:
    print derle.search(i).group()
GNU/Linux ve Windows için kullanımlarda ufak farklılıklar bulunmakta. Bu farklılıklara dikkat etmemiz gerekir. Düzenli İfadeler ile Karakter Dizisi Değiştirme İşlemleri
Şimdiye kadar düzenli ifadelerde sürekli eşleştirme işlemleri yaptık. Düzenli ifadeler sadece bu işlem için kullanılmamaktadır. Düzenli ifadeler ile bir karakter dizisini değiştirmemizi de sağlar. Bu iş için temel olarak sub() ve subn() metotları kullanılır.
sub() Metodu
#-*-coding:utf8-*-

import re

metin = "Dünyanın en popüler sporu futbol'dur.Futbol çok eğlencelidir."

derle = re.compile("Futbol",re.I)

print derle.sub("Basketbol",metin)

Dünyanın en popüler sporu Basketbol'dur.Basketbol çok eğlencelidir.
En basit haliyle sub() metodunu kullanmış olduk. "Futbol" karakter dizilerini "Basketbol" ile değiştirmiş olduk. Daha önceden görmüş olduğumuz "re.I" seçeneği ile büyük,küçük harf uyumunu ortadan kaldırdık.
Not:sub() metodu karakter dizilerinde öğrendiğimiz replace() metoduna çok benzer. Fakat sub() metodu hem replace() metodundan daha güçlüdür hemde beraber kullanılabilen derleme seçenekleri ile daha esnektir. Ama tabi ki replace() metodu işimiz için yeterli ise onu kullanmalıyız.
subn() Metodu
subn() metodu sub() metodu ile neredeyse aynıdır. Tek fark olarak yapılan değişiklik sayısını da çıktı olarak vermesidir. Bu metot çıktı olarak iki ögeli bir demet vermektedir. Birinci öge değiştirilen metin ikinci öge ise yapılan değişiklik sayısıdır.
#-*-coding:utf8-*-

import re

metin = "Dünyanın en popüler sporu futbol'dur.Futbol çok eğlencelidir."

derle = re.compile("Futbol",re.I|re.U)

degistir = derle.subn("Basketbol",metin)

print "Metin üzerinden %s değişiklik yapılmıştır."%(degistir[1])

Metin üzerinden 2 değişiklik yapılmıştır.
Gördüğünüz gibi kaç değişiklik yaptığımıza rahat bir şekilde ulaşmış olduk.
Not:Düzenli ifadeler konusunu bitirdik. Bu konunun sonunda şunu söylemeliyiz ki, eğer yapmak istediğimiz işlemleri karakter dizileri metotları ile yapabiliyorsak, bu metotları kullanmalıyız. Çünkü karakter dizileri metotları hem daha hızlı hemde daha basittir.

10 Temmuz 2013 Çarşamba

PYQT ILE PYTHON GUI GELIŞTIRME - 2

Portalımızı takip eden yeni python geliştirici adaylarımız, pythonun ne kadar kolay ve anlaşılır bir dil olduğunu fark etmişlerdir diye düşünmekteyiz. Konu Grafiksel Kullanıcı Arayüzü geliştirme olunca durum gene farksız.

Bu yazımızda Not Ortalaması  uygulaması yazacağız. Bu uygulamamızda basit özellikler olacaktır. Bu özellikler aşağıda listelenmiştir.



  • 1.  vize notu istenecektir.
  • 2. vize notu istenecektir.
  • Final notu istenecektir.
  • Girdilerin sadece integer değerler olması kontrol edilecektir.
  • 3 sınavın ortalaması alınıp ekrana yazılacaktır.

from __future__ import division
from PyQt4.QtGui import *
from PyQt4.QtCore import *


class ortalamaHesapla(QWidget):
    def __init__(self, parent=None):
        super(ortalamaHesapla, self).__init__(parent)

        self.metin = "
Sinav Ortalamasi Hesaplama
" self.grid = QGridLayout() self.baslik = QLabel(self.metin) self.vizeA = QLabel('1. Vize Notunuz ') self.vizeB = QLabel('2. Vize Notunuz ') self.final = QLabel('Final Notunuz ') self.vizeAdeger = QLineEdit() self.vizeBdeger = QLineEdit() self.finalDeger = QLineEdit() self.sonuc = QLabel('Ortalama ') self.sonucDeger = QLabel('0.00') self.hesapla = QPushButton('Hesapla') self.grid.addWidget(self.baslik, 0, 0, 1, 2) self.grid.addWidget(self.vizeA, 1, 0) self.grid.addWidget(self.vizeAdeger, 1, 1) self.grid.addWidget(self.vizeB, 2, 0) self.grid.addWidget(self.vizeBdeger, 2, 1) self.grid.addWidget(self.final, 3, 0) self.grid.addWidget(self.finalDeger, 3, 1) self.grid.addWidget(self.sonuc, 4, 0) self.grid.addWidget(self.sonucDeger, 4, 1) self.grid.addWidget(self.hesapla, 5, 0, 1, 2) self.connect(self.hesapla, SIGNAL('pressed()'), self.hesapYap) self.setLayout(self.grid) self.setWindowTitle("Not Hesaplama ~ PythonDersleri") def hesapYap(self): ortalama = 0 try: ilk_vize = int(self.vizeAdeger.text()) ikinci_vize = int(self.vizeBdeger.text()) final_notu = int(self.finalDeger.text()) ortalama = (ilk_vize + ikinci_vize + final_notu)/3 except: self.sonucDeger.setText('Tam sayi giriniz!') return self.sonucDeger.setText('%0.2f' % ortalama) uyg = QApplication([]) pencere=ortalamaHesapla() pencere.show() uyg.exec_()



Şimdi sizlere kodları açıklayalım. İlk başta bölme işleminde float sonuçların çıkması için division modülü eklenmiştir. Ardından grafiksel kullanıcı arayüzü için gerekli pyqt4 modülleri eklenmiştir.

Grafiksel Kullanıcı Arayüzü geliştirirken iç içe olan birden fazla widget'ler olmaktadır. Tüm widgetları ve pencereleri tek bir dosyada tutmak kod karmaşıklığına neden olmaktadır. Bu nedenle tüm widget'lar farklı dosyalarda sınıf olarak tanımlanarak daha sonra ana uygulamada kullanılabilir.


QGridLayout, ızgara yerleşkesidir. Pencerenizi bir ızgara olarak düşünürseniz, sol üstte ki ilk alan 0, 0 noktasıdır. Oluşturacağımız label, buton vs görselleri bu koordinat sistemine yerleştireceğiz. Bu nedenle QGridlayout'un  addWidget metodunun parametrelerini inceleyelim.

addWidget(eklenecek item, satir, satun, satir genişliği, sutun genişliği);

Örnek olarak; addWidget(ders_adi, 0, 0, 1, 2)

ders_adi  item'ini sıfırıncı  satırın  sıfırıncı  sütununa yerleştir. Bir adet satır genişliğinde olsun ama iki adet sütun genişliğinde yer kaplasın. Sadece satır ve sütun koordinatları verilirse, default olarak kapladığı satır ve sütun alanları 1 olarak atanmaktadır.

15 ile 24. satırlar arasında gerekli Label ve LineEdit elemanlarımız tanımlanmakta. 26 ile 35. satırlar arasında ise bu elemanlarımız GridLayout'umuza eklenmekte. Eklenme sırasına ve atanan koordinatlara lütfen dikkat ediniz.

37 ve 40. satırlarda yapılan işlemlere ilk yazımızdan aşına olduğunu düşünmekteyiz.

hesapYap metodu incelendiğinde ise text box'lardan text() metodu ile değerlerin okunduğu. Bunların integer değerlere dönüştürüldüğü görülmektedir. Ardından bölme işlemi gerçekleşmektedir. Bu işlemler try;except blokları arasında tanımlanmıştır. Bu hata gerçekleşir ise bunun muhtemel nedeni text box'ların boş bırakılması veya string değer girilmesidir. Bu durumda sonucDeger label'ının değeri kırmızı font'ta hata yazısı yazacak şekilde değiştirilmiştir. Eğer tüm işlemler doğru şekilde gerçekleşir ise, sonuç 52.  satırda ekrana yansıtılmaktadır. %0.2f ise sonucun sadece virgülden sonra ki sadece 2 basamağın yazılmasını ifade etmektedir.




ALIŞTIRMALAR:

 Bu uygulamaya ek özellikler ekleyebilirsiniz;
1 -uygulama açıldığında 640x480 boyutlarında açılsın.
2 -Boş değer veya string girişlerinde ki hataların birbirinden ayrılması. Örnek olarak ; "1. vize notuna değer girmediniz" veya "Final notu alanı sadece tam sayı içerebilir" gibi hataların yakalanması.
3 - Küsüratı .33 olan değerlerin .50 değerine, .66 olanların iste bir üst tam sayıya yuvarlanması.
4 - Hesapla butonunun yanına "Formu Temizle" butonunun eklenmesi ve tıklandığında formun temizlenmesi.

Bu özellikleri eklerken yaşadığınız problemleri konu altına yorum olarak yazabilirsiniz. Ekip problemlerinize çözüm üretmeye çalışacaktır.

























8 Temmuz 2013 Pazartesi

PyQT ile Python GUI Geliştirme - 1

QT, TrollTech firması tarafından platform bağımsız grafik arayüz geliştirmek üzere geliştirilmektedir. Pek çok programlama dili ile birlikte kullanılabilen QT, python diliylede birlikte kullanılabilmektedir.

Python için QT Riverbank firması tarafından geliştirilmektedir.



Aşağıda ki linkten gerekli Python versiyonuna ve işletim sistemine ait paketi indirip kurunuz.

http://www.riverbankcomputing.com/software/pyqt/download

Yazı serimiz boyunca IDE olark PyCharm IDE'si kullanılacaktır. Siz dilediğiniz tüm metin editörlerini ve IDE'leri kullanabilirsiniz.

Aşağıda ki kodları yazıp çalıştırdığımızda ekrana küçük bir pencere gelecektir.


from PyQt4.QtGui import *

app = QApplication([])
label = QLabel('<h1>Python Dersleri</h1>')
label.show()
app.exec_()


1. satır = QT'yi kullanabilmek için gerekli modüller import edilmekte.
2. satır = QApplication nesnesi oluşturulmuştur. QT uygulamaları bu nesne üzerinden çalışmaktadır.
3. satır = Bir adet Label tanımlanmıştır. Swing ile JAVA'da yada C# dilinde GUI geliştirilirken tanımlanan label'lar gibi düşünebilirsiniz. QLabel içerisinde html tag'lerini kullanabilirsiniz.
4. satır = Label gibi widget'lerin uygulamada görüntülenmesi için show() metodu çağırılmıştır.
5. satır = exec_ metodu ile QT uygulamamız çalıştırılmıştır. Kullanıcı ile etkileşimler exec_() üzerinden yakalanmaktadır.


from PyQt4.QtGui import *
from PyQt4.QtCore import *

app = QApplication([])

window = QWidget()
window.setWindowTitle('PythonDersleri.com')
txtLabel = QLabel('Python Dersleri')
btnButton = QPushButton('Change')


def changeTxtLabel():
    txtLabel.setText('Python Ogreniyorum')

window.connect(btnButton, SIGNAL('pressed()'), changeTxtLabel)

dizayn = QHBoxLayout()
dizayn.addWidget(txtLabel)
dizayn.addWidget(btnButton)

window.setLayout(dizayn)
window.show()
app.exec_()



1. ve 2. satır = Gerekli QT modülleri import edilmiştir.
4. satır = QApplication nesnesi oluşturulmuştur.
6. satır = Bir adet Widget oluşturulmuştur. Butona basıldığı oluşan sinyal bu widget üzerinden yakalanmaktadır.
7. satır = Pencerenin başlığına yazı atanmıştır.
8. satır = Bir adet Label oluşturulmuştur.
9. satır = Buton oluşturulmuştur. Bu butona basıldığında oluşturulan Label'in içeriği değiştirilecektir.
12. satır = Bir fonksiyon tanımlanmıştır. Bu fonksiyon txtLabel'a yeni text atamaktadır.
15. satır = btnButton isimli butona basıldığında pressed() sinyali yayınlanır. Bu sinyali window isimli bizim tarafımızdan oluşturulan QWidget'ın connect metodu ile yakalamaktayız. 3. parametre olarak ise bu butona basıldığında hangi fonksiyonun çağırılacağını söylüyoruz. Bu şekilde butonumuza basıldığında QLabel'ımızın text'i değişecektir.
17. satır = Bir adet QHBoxLayout oluşturulmakta. Bu layout ile label ve butonumuz yan yana sıralanacaktır. Alt alta sıralamak istiyorsanız QVBoxLayout kullanabilirsiniz.
18 ve 19. satır = Oluşturduğumuz label ve buton bu layout içerisine yerleştirilir.
21. satır = Layout ise tanımladığımız window isimli widget'a atanmaktadır.

Ev Ödevi :

Bir dizide sizin tarafınızdan tanımlanmış 10 adet eleman bulunmaktadır. Bu elemanlar her butona basıldığında label'e sırasıyla atanacaktır. Ayrıca üstte label olmak üzere buton ve label'imizin alt alta olması istenmektedir.

3 Temmuz 2013 Çarşamba

Düzenli İfadeler - Metakarakterler

Düzenli ifadeler elle yapılması saatler alacak olan bir işlemi saliseler içinde yapmamızı sağlar.Düzenli ifadeler ile karakter dizileri üzerinde işlemler yapabiliriz.Burada hemen şunu da söyleyelim ki; eğer yapmak istediğimiz işlemi karakter dizileri metotları ile yapabiliyorsak kesinlikle bu metotları kullanmalıyız. Çünkü karakter dizileri metotları hem daha basit hemde çok daha hızlıdır.
Düzenli ifadeler Python programlama dilinin en zor konularından biridir. Ama öğrendikten sonra çok zor olan işlemleri çok basit bir şekilde yapmamızı sağlar. Zorluğundan dolayı kavrayabilmek için bol bol örnek çözülmesi gereken bir konudur.
Kullanım Yerleri
Nasıl yazıldığını tam olarak bilmediğimiz bir karakter dizisini aratabiliriz.
  • Örneğin; "congratulations" karakter dizisinin bulmak istiyor ve yazılışını tam olarak bilmiyorsak ilk ve son bir kaç karakterini verip aratabiliriz.
Bir metnin içindeki özel bir forma uyan parçaları bulabiliriz.
  • Örneğin; bir metin içindeki tüm URL'leri ana yapıyı tarif ederek ayıklayabiliriz.(http:// ile başlayan ve arada noktalar içeren kelimeler.)
Aldığımız verinin belli bir formata uygun olup olmadığını kontrol edebiliriz.
  • Örneğin; kullanıcıdan e-posta istediğimizde formatını kontrol edebiliriz. (@ içerecek ve ikinci blokta bir nokta bulunacak.)
Belli bir formatta aldığımız bir veriyi başka bir formatta dönüştürebiliriz.
  • Örneğin; Bir metin dosyasından aldığımız verileri kullanmak için Php dizisine dönüştürebiliriz.
Düzenli İfadelerin Metotları
Pythonda düzenli ifadeler ile ilgili her şey bir modül içinde tutulmaktadır. Bu modülün adı "re(regular expression)"dır. Tabi ki bu modülü kullanabilmemiz için ilk önce içe aktarmamız gerekir.
import re
Bu kod parçacığı ile modülü içe aktarmış olduk. Şimdi gelin bu modülün bize sunduğu tüm özellikleri listeleyelim.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

for i in dir(re):
    print i

DEBUG
DOTALL
I
IGNORECASE
L
LOCALE
M
MULTILINE
S
Scanner
T
TEMPLATE
U
UNICODE
VERBOSE
X
_MAXCACHE
__all__
__builtins__
__doc__
__file__
__name__
__package__
__version__
_alphanum
_cache
_cache_repl
_compile
_compile_repl
_expand
_pattern_type
_pickle
_subx
compile
copy_reg
error
escape
findall
finditer
match
purge
search
split
sre_compile
sre_parse
sub
subn
sys
template
Gördüğünüz gibi düzenli ifadeler bize bir çok metot/fonksiyon kullanma imkanı veriyor. Eğer herhangi bir metot/fonksiyon hakkında bilgi almak isterseniz. help(metot/fonksiyon adi) şeklinde kullanabilirsiniz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

print help(re.escape)

  Help on function escape in module re:

escape(pattern)
    Escape all non-alphanumeric characters in pattern.
Gelin şimdi biz bu metotlar içinde en sık kullanılanları açıklayalım.
Match() Metodu
match() metodu bir karakter dizisinin bizim aradığımız bir başka karakter dizisi ile başlayıp başlamadığını kontrol eder. Yani karakter dizisinin sadece en başına bakar.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

karakter = "python programlama dilini öğreniyorum."
print  re.match("python",karakter)
Düzenli ifade kalıpları match() metodunun ilk argümanıdır. İkinci argüman ise arama yapacağımız karakter dizisidir.Yukarıdaki kodları çalıştırdığınızda şu şekilde bir çıktı alacaksınız.
<_sre data-blogger-escaped-.sre_match="" data-blogger-escaped-0xb728e790="" data-blogger-escaped-at="" data-blogger-escaped-object="">
Bu ifade karakter dizisinin düzenli ifade ile eşleştiği anlamına gelir. match() metodu düzenli ifade ile karakter dizisinin eşleşip eşleşmediğini bize söyler. Eşleşti deyiş biçimi de bu şekildedir. Bu ifadeye Python'da "eşleşme nesnesi" denir.
print  re.match("delphi",karakter)
None
Burada eşleşme olmadığı için match() metodu geriye "None" ifadesi döndürdü. Yani match() metodu geriye eşleşme varsa "eşleşme nesnesi" yoksa "None" ifadesi döndürür.
En başta da söylediğimiz gibi match() metodu karakter dizisinin sadece en başına bakar.Gelin şu şekilde bir örnek verelim:
import re

karakter = "python programlama dilini öğreniyorum."
print  re.match("programlama",karakter)
None
"programlama" kelimesi karakter dizisi içinde bulunduğu halde "programlama" ile başlamadığı için match() metodu geriye "None" ifadesini döndürdü.
Biz bu yaptığımız işlemleri karakter dizisi metotları ile yapabilir miyiz?
karakter = "python programlama dilini öğreniyorum."
print karakter.split()[0]=="python"
True
print karakter.split()[0]=="programlama"
False
print karakter.startswith("python")
True
Bizim düzenli ifadelerden beklediğimiz sadece karakter dizisinin başlangıç ifadesini kontrol etmekse bunu karakter dizisi metotları ile yapmamız daha mantıklı olacaktır. Çünkü split() ve startswith() metotları match() metoduna göre hem daha basit hemde hızlıdır.
match() metodu bize bir eşleştirme nesnesi döndürüyor ve biz bulunan şeyi göremiyoruz. Eğer görmek istersek group() metodunu kullanabiliriz.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("python",karakter)
print kontrol.group()

python
Burada re.match("python",karakter) metodu ile dönen eşleştirme nesnesini bir değişkene atadık. Bu eşleştirme nesnesinin de kendi metotları bulunmaktadır.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("python",karakter)

for i in dir(kontrol):
    print i
__class__
__copy__
__deepcopy__
__delattr__
__doc__
__format__
__getattribute__
__hash__
__init__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__
end
endpos
expand
group
groupdict
groups
lastgroup
lastindex
pos
re
regs
span
start
string
Listedeki metotlar eşleştirme nesnesi metotlarıdır. Dikkat ederseniz az önce kullandığımız group() metodu da listede bulunmaktadır.
Eğer eşleştirme nesnesi değilde geriye "None" ifadesi dönerse group() metodu hata verecektir.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("programlama",karakter)

print kontrol.group()

Traceback (most recent call last):
  File "/home/mazlumagar/workspace/Python/Duzenli İfadeler/match.py", line 9, in 
    print kontrol.group()
AttributeError: 'NoneType' object has no attribute 'group'
Bu hata mesajı programın çökmesine sebep olur. Bu yüzden kodlarımızı şu şekilde yazabiliriz.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match("python",karakter)

if kontrol:
    print "Eşleşen kelime: " + kontrol.group()
else:
    print "Eşleşme başarısız."
search() Metodu
match() metodu karakter dizisinin sadece en başına bakıyor ve bir eşleştirme işlemi yapıyordu. search() metodu ise karakter dizisinin genelinde bir arama işlemi yapar.
import re
 
karakter = "python programlama dilini öğreniyorum."
print  re.match("programlama",karakter)
None
Bu örneği hatırlarsanız; match() metodu burada karakter dizisinin başında "programlama" ifadesini bulamadığı için "None" ifadesi döndürüyordu. Şimdi aynı örneği search() metodu ile yapalım.
import re
 
karakter = "python programlama dilini öğreniyorum."
print  re.search("programlama",karakter)

<_sre data-blogger-escaped-.sre_match="" data-blogger-escaped-0xb7239918="" data-blogger-escaped-at="" data-blogger-escaped-object="">
Gördüğünüz gibi search() metodu "programlama" ifadesini tüm karakter dizisinde aradı ve bulduğu için geriye "eşleşme nesnesi" döndürdü.
Not:match() metodunda bahsettiğimiz eşleşme nesneleri metodları search() metodu içinde geçerlidir.
Not:Düzenli ifadeler sadece karakter dizileri üzerinde işlem yapmamızı sağlar.Listeler, sözlükler gibi yapılar üzerinde doğrudan düzenli ifadeleri kullanamayız.
import re

liste = ["python","delphi","c++","c"]
re.search("python",liste)

Traceback (most recent call last):
  File "/home/mazlumagar/workspace/Python/deneme.py", line 6, in 
    re.search("python",liste)
  File "/usr/lib/python2.7/re.py", line 142, in search
    return _compile(pattern, flags).search(string)
TypeError: expected string or buffer
Gördüğünüz gibi program hata verdi. Listeler üzerinde işlem yapmak isterseniz şu şekilde bir kullanım yapabilirsiniz.
import re

liste = ["python","delphi","c++","c"]

for i in liste:
    arama = re.search("python",i)
    if arama:
        print arama.group()

python
findall() Metodu
findall() metodu karakter dizisi içinde aranan öğrenin hepsini bir liste şeklinde geriye döndürür.
import re

python ="""Python, nesne yönelimli, yorumlanabilen, birimsel (modüler) ve etkileşimli bir programlama dilidir.
Girintilere dayalı basit sözdizimi, dilin öğrenilmesini ve akılda kalmasını kolaylaştırır.Bu
da ona söz diziminin ayrıntıları ile vakit yitirmeden programlama yapılmaya başlanabilen bir dil olma özelliği kazandırır.
Modüler yapısı, sınıf dizgesini (sistem) ve her türlü veri alanı girişini destekler. Hemen hemen her türlü platformda çalışabilir.
(Unix , Linux, Mac, Windows, Amiga, Symbian). Python ile sistem programlama, kullanıcı arabirimi programlama, ağ programlama, uygulama ve veritabanı
yazılımı programlama gibi birçok alanda yazılım geliştirebilirsiniz. Büyük yazılımların hızlı bir şekilde prototiplerinin üretilmesi ve
denenmesi gerektiği durumlarda da C ya da C++ gibi dillere tercih edilir."""

print re.findall("Python",python);

['Python', 'Python']
Gördüğünüz gibi aradığımız "Python" kelimesi kaç tane varsa hepsini liste şeklinde geriye döndürdü. Programı şu hale de getirebiliriz.
kelime = raw_input("Aradığınız kelimeyi giriniz:")

print kelime + " karakter dizisinde " , len(re.findall(kelime,python)) , " kere geçmektedir."

Aradığınız kelimeyi giriniz:Python
Python karakter dizisinde  2  kere geçmektedir.
Metakarakterler
Şimdiye kadar kullandığımız düzenli ifadelerde, düzenli ifade ve karakter dizisi arasında doğrudan bir eşleşme yaptık. Bu yaptıklarımız düzenli ifadelerin en temel halidir. Yani "python" düzenli ifadesini karakter dizisinde bulmak için "python" kelimesini kullandık. "python" düzenli ifadesini doğrudan kendisi ile eşleştirmiş olduk. Peki bunları neden söylüyoruz ? Düzenli ifadelerden bu şekilde doğrudan eşleştirme yapmadan da arama yapmamızı sağlayan ifadeler vardır. Zaten düzenli ifadeleri özel kılan bu ifadelerdir.
Bu ifadelere Python'da metakarakterler denir. Aslında biz metakarakterleri daha önceden de kullanmıştık.
print "Python\nGeleceğin programlama dili"
Python
Geleceğin programlama dili
Bu örnekte gördüğünüz gibi Python "\n" ifadesini gördüğünde ekrana yazmak yerine yeni satıra geçmesi gerektiğini biliyor. Söylediğimiz gibi "\n" kendisiyle doğrudan eşleşmedi. Aynı şekilde "\t" ifadesini gördüğü zaman "tab" bırakması gerektiğini anlıyor.
print "Python\tGeleceğin programlama dili"
Python Geleceğin programlama dili
Düzenli ifadeleri düzenli ifade yapan bu metakarakterlerdir. Python bu karakterleri gördüğü zaman doğrudan eşleştirme yapmak yerine farklı tepkiler verecektir. Metakarakterler olmadan düzenli ifadeler ile çok faydalı işler yapmak mümkün değildir.
Python da bulunan metakarakterler:<\br> [ ] . * + ? { } ^ $ | ( )<\br> Şimdi gelin bu karakterleri sırası ile işlemeye başlayalım. Zaten açıkladıkça ne demek istediğimiz anlayacaksınız.
[ ](Köşeli Parantez)
[] metakarakterini açıklamaya çalışmak yerine gelin hemen örnek verelim.
liste = ["özcan demir", "mehmet", "süleyman",
         "selim", "kemal", "özkan nuri", "esra", "dündar",
         "esin", "esma", "özhan kamil", "özlem"]
Elimizde bu şekilde bir liste olsun. Biz daha önceden gördüğümüz yöntemler ile bu listeden bir öge bulmak istersek, örneğin "özkan", şu şekilde kullanmamız gerekir.
for i in liste:
    arama = re.search("özkan",i)
    if arama:
        print  arama.group()
özkan
Eğer arama yapmak istediğimiz öge birden fazla ise biz bu yaptığımızı hepsine tek tek uygulamamız gerekir. İşte tam bu nokta da [] metakarakteri yardımımıza koşuyor.
for i in liste:
    arama = re.search("öz[ckh]an",i)
    if arama:
      print  arama.group()
özcan
özkan
özhan
İşte sizinde gördüğünüz gibi tek tek hepsine uygulamak yerine değişen kısmı [] ifadesi içine aldık. Python köşeli parantez içinde gördüğü bütün karakterleri tek tek eşleştirme yapacağı karakter dizisine uyguluyor.İlk önce "öz" ile başlayan bütün ögeleri buluyor, ardından "c" harfi ile devam eden ve "an" ile biten ögeyi buluyor. Böylece "özcan" ifadesini bulmuş oldu. Bu yaptığı işlemi [] parantez içindeki bütün karakterlere sırasıyla uyguluyor.
Bu örnekte search() metodunu kullandığımıza dikkat edin. Şimdi gelin match() metodunu kullanarak yeni örnek yapalım.
import re

sifre = raw_input("Lütfen şifre oluşturun:")

if re.match("[0-9]",sifre):
    print "Şifre sayı ile başlayamaz."
else:
    print "Şifre başaarıyla oluşturuldu."
Lütfen şifre oluşturun:123sifre
Şifre sayı ile başlayamaz.
Gördüğünüz gibi kullanıcıdan bir şifre istedik ve bu şifrenin sayı ile başlaması durumunda kullanıcıyı uyardık. Burada [0-9] ifadesi sayıları temsil ediyor. Eğer rakam kontrolü yapmak isteseydik [a-z],[A-Z] şeklinde kullanabilirdik.Aynı örneği şu şekilde değiştirebiliriz.
import re

sifre = raw_input("Lütfen şifre oluşturun:")

if re.match("[0-9, ]",sifre):
    print "Şifre sayı veya boşluk ile başlayamaz."
else:
    print "Şifre başaarıyla oluşturuldu."
[] metakarakterini kullanırken bu örnekte olduğu gibi , ile ayırarak birden fazla kontrol yapabiliyoruz.Son olarak şu şekilde bir örnek verelim
import re

karakter ="TY76Z"

if re.match("[A-Z][A-Z][0-9]",karakter):
    print "Aranılan ifade bulundu"
else:
   print "Aranılan ifade bulunamadı"
Aranılan ifade bulundu
Bu örnekte de ilk iki karakterin büyük harf ve onlardan sonra gelen karakterin ise sayı olmasını istediğimizi belirttik.
.(Nokta)
"." metakarakteri yeni satır hariç bütün karakterleri temsil etmek için kullanılır. [] metakarakterinde verdiğimiz örneği değiştirelim.
for i in liste:
    arama = re.search("öz.an",i)
    if arama:
      print  arama.group()
özcan
özkan
özhan
"." metakarakteri tek bir karakterin yerini tutar. Birden fazla karakteri temsil edemez.
import re

liste = ["ali","veli", "ahmet", "hasan"]

for i in liste:
    if re.match(".li",i):
        print i
ali
Bu örnekte gördüğünüz gibi geriye sadece "ali" ifadesi döndü. "." metakarakteri bir karakter temsil ettiği için "ali" ifadesini buldu. Fakat "Veli" ifadesinde iki karakter olduğu için bulamadı. Birden fazla karakterin yerini tutan metakarakteri daha sonra inceleyeceğiz.
import re

numara = raw_input("Okul numaranızı giriniz:")

if re.match(".[0-9][a-z][0-9,a-z]",numara):
    print "Okul numarası kabul edildi." 
else:
    print "Okul numarası formata uygun değil"  

Okul numaranızı giriniz:.8s7
Okul numarası kabul edildi.
Bu örnekte kullanıcıdan numara istedik ve gelin bu numaranın koşullarını sıralayalım:
  • İlk karakteri herhangi bir karakter olabilir.
  • İkinci karakteri sayı olmak zorunda.
  • Üçüncü karakteri küçük harf olmak zorunda.
  • Dördüncü karakteri sayı veya küçük harf olabilir.
*(Yıldız)
"*" metakarakteri düzenli ifadede konulduğu yerden bir önceki karakteri sıfır veya daha fazla sayıda eşitler. Tanımı biraz karışık ama örnek verince netleşecektir.
 #!/usr/bin/env python
# -*- coding: utf-8 -*-


import re

yildiz = ["kd","kod","kood","koood","boş"]
    
for i in yildiz: 
    if re.match("ko*d",i):   
        print i
kd
kod
kood
koood
Bu örnekteki çıktımızı incelerseniz sadece "*" metakarakterinden bir önceki karakterin adeti değişiyor. İşte sıfır ve daha fazla sayıda eşitler derken kastettiğimiz tam olarak buydu. "*" metakarakteri kendinden önceki sadece bir karakter ile ilgilenir. Yani burada sadece "o" karakterinin sıfır veya daha fazla sayıda bulunup bulunmadığını kontrol eder.
Burada yazdığımız düzenli ifade ile aradığımız ifadenin "k" ile başlamasını sonra sıfır veya daha fazla sayıda "o" ile davam etmesini ve "d" ile bitmesi gerektiğini söylüyoruz.
Şimdi gelin daha önceden öğrendiğimiz "." metakarakteri ile "*" metakarakterini birleştirelim ve bakalım ne olacak?
 #!/usr/bin/env python
# -*- coding: utf-8 -*-


import re

liste = ["Ahmet","Mehmet","Muhammet","Ali","Veli","Haşmet"]

for i in liste:
    if re.match(".*met",i):
        print i
Ahmet
Mehmet
Muhammet
Haşmet
Gördüğünüz gibi "met" ile biten bütün ögeleri listeledi. Hatırlarsanız "." bütün karakterleri temsil ediyordu. "*" ise kendinden önce gelen karakteri sıfır veya daha fazla sayıda eşitliyordu. Yani biz burada şu komutu verdik; bana karakter dizisi başında herhangi bir karakteri ("." ile) sıfır veya daha fazla sayıda içeren ve "met" ile biten ögeleri listele. Bu şekilde "met" ile biten kendisi de dahil olmak üzere her ögeyi listeler.
"*" sayesinde match() metodunu search() metodu gibi de kullanabiliriz. Daha önceden search() ile yaptığımız örneği şu hale getirelim.
import re

karakter = "python programlama dilini öğreniyorum."
kontrol = re.match(".*programlama",karakter)

if kontrol:
    print "Aranılan öğe bulundu."
else:
    print "Aranılan öğe bulunamadı."
Aranılan öğe bulundu.
Not: Tabi ki search() metodunu kullanmak performans açısından çok daha iyidir.
+(Artı)
"+" metakarakteri "*" metakarakterine oldukça benzerdir. "*" kendisinden önceki sıfır veya daha fazla sayıda tekrar eden karakterleri ayıklıyordu."+" ise kendisinden önceki bir veya daha fazla sayıda tekrar eden karakteri ayıklar.
"*" metakarakterini işlerken verdiğimiz örneği hatırlarsanız, "kd" ögesini de çıktı olarak alıyorduk. Biz her zaman böyle olmasını istemeyebiliriz. Aradığımız karakterin öge içinde en az bir kere geçmesini istediğimiz durumlarda "*" yerine "+" metakarakterini kullanmalıyız.
import re

arti = ["kd","kod","kood","koood","boş"]
    
for i in arti: 
    if re.match("ko+d",i):   
        print i
kod
kood
koood
Gördüğünüz gibi bu sefer "kd" ögesi geriye dönmedi.
Hatırlarsanız [] metakarakterini işlerken şöyle bir örnek vermiştik.
import re
 
karakter ="TY76Z"
 
if re.match("[A-Z][A-Z][0-9]",karakter):
    print "Aranılan ifade bulundu"
else:
   print "Aranılan ifade bulunamadı"
Burada aradığımız ifadenin ilk iki ögesinin büyük harf olmasını belirtmek için iki kere [A-Z] ifadesini kullandık. Ama şimdi "+" metakarakterini öğrendiğimize göre şu hale getirebiliriz.
import re
 
karakter ="TYS76Z"
 
if re.match("[A-Z]+[0-9]",karakter):
    print "Aranılan ifade bulundu"
else:
   print "Aranılan ifade bulunamadı"
Aranılan ifade bulundu
İlk örneğimizde aranılan ifadenin ilk iki karakterinin büyük harf sonraki karakterin ise sayı olması gerekir. Ama "+" metakarakterini kullanarak yaptığımız örnekte bu sınırlama ortadan kalktı. Bir veya birden fazla sayıda büyük harf olabilir.
?(Soru İşareti)
Önceki bölümlerde işlediğimiz "*" metakarakteri eşleşmenin sıfır veya daha fazla olduğu durumlarda "+" metakarakteri ise eşleşmenin bir veya daha fazla olduğu durumlarda kullanılıyordu. "?" metakarakteri ise eşleşme sayısının sıfır veya bir olduğu durumlarda kullanılır.
Daha önce yaptığımız örneğin üç metakarakter ile kullanımını gösterelim ki aradaki farkı net bir biçimde görelim.
import re
yildiz = ["kd","kod","kood","koood","boş"]
    
for i in yildiz: 
    if re.match("ko*d",i):   
        print i
kd
kod
kood
koood

import re

arti = ["kd","kod","kood","koood","boş"]
    
for i in arti: 
    if re.match("ko+d",i):   
        print i
kod
kood
koood

import re

soru = ["kd","kod","kood","koood","boş"]
    
for i in soru: 
    if re.match("ko?d",i):   
        print i
kd
kod
Gördüğünüz gibi "?" çıktı olarak sıfır ve bir karakter barındıran "kd" ve "kod" ifadelerini geriye döndürdü.
{}(Küme Parantezi)
{} merakarakteri sayesinde bir eşleşmenin kaç adet olması gerektiğini belirtebiliyoruz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import re
 
kume = ["kd","kod","kood","koood","boş"]
     
for i in kume: 
    if re.match("ko{2}d",i):   
        print i
kood
Gördüğünüz gibi, biz küme parantezini kullanarak "o" karakterinin iki adet olmasını istediğimizi belirttik. Python da bize sadece "kood" ifadesini döndürdü.
{} küme parantezinin bir başka kullanım şekli ise; bir karakterin en az ve en çok kaç kere tekrar etmesi gerektiğini söyleyebiliyoruz. Hemen örneğine bakalım.
for i in yildiz: 
    if re.match("ko{0,2}d",i):   
        print i
kd
kod
kood
Bu sefer Python bize "o" karakterinin hiç olmadığı durumdan 2 adet olduğu duruma kadar geri döndürmüş oldu.
liste = ['23BH56','TY76Z','4Y7UZ','TYUDZ','34534','1agAY54']
   
for i in liste: 
    a=re.search("[A-Z].[0-9]",i)
    if a:   
        print a.group()
^(Şapka)
Hatırlarsanız daha önceki konularda match() ve search() metodlarını işlemiştik. match() metodu arama yaparken ifadenin sadece başına bakar search() metodu ise aranılan ifadeyi tüm öge içinde arardı.
^ metakarakteri ile ise search() motodu ile arama yaparken match() metodu gibi ifadenin sadece başına bakmasını istediğimizi belirtiyoruz.
import re
 
liste = ['23BH56','TY76Z','4Y7UZ','TYUDZ','34534','1agAY54']
   
for i in liste: 
    a=re.match("[A-Z]+[0-9]",i)
    if a:   
        print i
TY76Z 
Burada Python'a aradığı öge için şu koşulu belirttik; aradığın öge bir veya daha fazla sayıda büyük harf ile başlayacak ve onları bir sayı takip edecek. Python'da bu koşula göre bize çıktı verdi. Burada dikkat etmeniz gereken match() metodunu kullanmış olmamız. Şimdi aynı örneği search() metodu ile kullanalım.
for i in liste: 
    a=re.search("[A-Z]+[0-9]",i)
    if a:   
        print i 
23BH56
TY76Z
4Y7UZ
1agAY54
Gördüğünüz gibi çıktı sayımız bir hayli arttı. match() metodu eşleştirme yaparken ifadenin sadece başına bakıyor search() metodu ise tüm ifade içinde eşleştirme yapıyordu. Şimdi aynı örnekte search() metodunu "^" metakarakteri ile beraber kullanalım.
for i in liste: 
    a=re.search("^[A-Z]+[0-9]",i)
    if a:   
        print i 
TY76Z
Gördüğünüz gibi search() metodundaki çıktının aynısını aldık. Biz burada yazdırma işlemi yaparken listenin elemanını yazdırıyoruz. Şu şekilde eşleştirme nesnesi ile dönen ifadeyi yazdıralım.
for i in liste: 
    a=re.search("[A-Z]+[0-9]",i)
    if a:   
        print a.group()
BH5
TY7
Y7
AY5
Bu sefer bize sadece aradığımız ögeyi geriye döndürdü. Eğer biz burada tüm ifadeyi döndürmesini istersek şu şekilde kullanabiliriz.
for i in liste: 
    a=re.search(".*[A-Z]+[0-9].*",i)
    if a:   
        print a.group()
23BH56
TY76Z
4Y7UZ
1agAY54
Gördüğünüz gibi tüm ifadeyi geriye döndürmüş olduk.
"^" metakarakterinin bir görevi daha vardır. Hariç anlamında da kullanılır. Yani arama işlemi yaparken belli bir koşula uyan ifadeleri almak istemeyebiliriz. Bu durumlarda da "^" metakarakterini kullanabiliriz.
for i in liste:
    nesne = re.match("[0-9A-Z][^0-9]",i)
    if nesne:
        print i
4Y7UZ
TYUDZ
1agAY54
Burada ifadenin harf veya sayı ile başlamasını ondan sonra ise sayı gelmemesini söyledik. Python da bize ona göre çıktı vermiş oldu.
$(Dolar)
"$" metakarakteri bir önceki bölümde incelediğimiz "^" metakarakterinin tam tersi işi yapar. "^" karakteri ile karakter dizilerinin nasıl başlayacağını belirtiyorduk. "$" metakarakteri ile de nasıl biteceğini belirtiyoruz.
Elimizde şu şekilde bir isim listesi olsun ve biz bu listeden ismi "an" ile bitenleri ayıklayalım.
liste = ['Hasan','ayşe','ahmet','Alkan','esra','Alıngan','Altan','veli']
   
for i in liste:
    if  re.search('an$',i):
        print i      
Hasan
Alkan
Alıngan
Altan
Gördüğünüz gibi çıktılar tamda beklediğimiz gibi oldu.
Not: Burada önemli olan "^" ve "$" metakarakterlerini search() metodu ile kullanmanız gerektiğidir. Eğer match() metodu ile kullanırsanız herhangi bir çıktı alamazsınız.
Ters Bölü
"\" işareti daha önceden de bildiğimiz kaçış dizisidir. Şimdiye kadar işlediğimiz metakarakterler kendileri ile eşleşmiyorlar. Yani bu metakarakterleri bir karakter dizisinde aramak istesek özel anlamları yüzünden bu mümkün olmayacaktır. İşte bu özel anlamlarını iptal edip bu karakterleri Python'a normak karakter gibi göstermek için "\" kaçış dizisini kullanıyoruz.
import re
 
liste = ['2+5','3*4','4/2','6+9','7+5','5-2']
   
for i in liste:
    if  re.match('[0-9]+/',i):
        print i   
4/2
Örneği açıklayalım. Biz burada Python'a aradığın öge sayı ile başlayacak, bu sayı bir veya daha fazla sayıda olabilir(+ metakarakteri) ve sonra / (Buradaki normal bölü işaretidir.) devam edecektir. Python da bu koşula uyan tek karakter dizisini bize döndürdü. Dikkat ederseniz buradaki "+" karakteri metakarakterdir yani özel bir anlamı vardır. Kendisinden önceki sayının bir veya daha fazla sayıda olabileceğini belirtiyor. Ama biz liste içinde sadece toplama (+) işlemi olan ögeleri getirmek isteseydik ne yapmamız gerekiyordu ? Örneğimize bakalım.
liste = ['2+5','3*4','4/2','6+9','7+5','5-2']
   
for i in liste:
    if  re.match('[0-9]+\+',i):
        print i       
2+5
6+9
7+5
Gördüğünüz gibi sadece toplama işlemi olan ögeleri ayıkladık. "\" işareti ile kendisinden sonra gelen "+" metakarakterinin özel anlamını elinden almış olduk. Yani sıradan bir karakter haline getirdik. Burada kullandığımız işaretin bölü(/) işareti olmadığına dikkat edin. Eğer bölü işaretini kullanırsanız ilk ifadedeki çıktıyı elde ederiz.
for i in liste:
    if  re.match('[0-9]+/+',i):
        print i 
4/2
Burada "+" metakarakteri özel anlamını yitirmedi. Yani biz bir veya daha fazla sayıda bölü (/) işareti ara demiş olduk.
|(Dik Çizgi)
"|" metakarakteri "veya" anlamına gelir. Birden fazla eşleştirme kalıbı kullanılmak istenen durumlarda kullanılır.
Bir önceki başlıkta verdiğimiz örnek üzerinden gidelim.
liste = ['2+5','3*4','4/2','6+9','7+5','5-2']
   
for i in liste:
    if  re.match('[0-9]+\*|[0-9]+\-',i):
        print i      
3*4
5-2
Bu örnekte gördüğünüz gibi iki ifadenin kalıbını "|" metakarakteri ile ayrı ayrı oluşturduk. Python da ikisine birden uyanı bize getirdi. Burada "\" kaçış dizisini kullanarak ilk önce sayı ile başlayan ve "*" ile devam edenleri veya sayı ile başlayan "-" ile devam edenleri getir demiş olduk.
Elimizdeki bir listede herhangi bir ögenin kendisini yazıyorsak da bu metakarakteri kullanabiliriz.
re.search("Galatasaray" | "Fenerbahçe" | "Beşiktaş")
() (Parantez)
"()" metakarakteri düzenli ifade kalıplarını gruplamamızı sağlar. Bu metakarakter sayesinde bir karakter dizisinin istediğimiz bölümlerini çok rahat bir şekilde ayıklayabiliriz.
İleride eşleşme nesneleri metotlarından group() metodunu işlerken örnekler vereceğiz.