Python3 ile MySQL Bağlantısı ve Sorgulama Yapmak (PyMySQL modülü)

Python 2.x sürümü ile MySQL bağlantısı yapmayı denediyseniz, muhtemelen fazla uğraşmadan bağlantıyı sağlamış ve istediklerinizi yapmışsınızdır. Yine de, en çok anlatılan MySQL modüllerinde sürüm uyumsuzluğundan kaynaklı problemler yaşadığımı hatırlıyorum. Özellikle Python3 üzerinde MySQL ile işlem yapmak istiyorsanız sorunun boyutu sürüm uyumsuzluğunun en üst seviyesine çıkabiliyor.

Bu konuda birçok modülü denedikten(ya da deneyemedikten) sonra pymysql adlı modülle karşılaştım. Bu modül Python’un hem 2.x hem de 3.x sürümleriyle çalışabildiği için de açıkçası işi ciddi anlamda rahatlatıyor. Bu yazıda bu modülü kullanmak isteyenlere bilgiler yer alacak.

Öncelikle, modülü indirdiğimizde içerisinde python 2.x sürümleri için kurulum dosyası yer alıyor. Bunu komut satırında python setup.py install komutunu vererek hem Windows hem de Linux altında kurabilirsiniz. Tabii ki setuptools’un kurulu olduğunu varsayıyorum. Zaten kurulu değilse alacağınız hatadan olmadığını anlayabilirsiniz.

Yine, python3 altında çalışırken de böyle bir kurulum yapacağız ancak öncesinde yapmamız gereken bir işlem var. Modülü indirdiğinizde içerisindeki readme dosyasına bakarsanız orada py2to3 aracıyla modülü python3 e çevirebilmeniz için komutlar yer alıyor. Ben Windows’ta beceremediğim için Linux altında çevirip hem Ubuntu’ma hem de aynı dosyalarla Windows’a rahatça kurabildim. Siz isterseniz yine Windows’ta deneyin. Sorun yaşayan olursa buradan python3 için çevrilmiş dosyaları da paylaşabilirim.

Kurulum hakkında detaylı bilgi readme dosyasında yer almakla birlikte, takıldığınız veya hata aldığınız noktaları sorabilirsiniz. Bu yazının esas konusu olan kurduğumuz bu modülü nasıl kullanacağımız konusuna gelelim.

Öncelikle, modülümüzü import ederek başlayalım:

import pymysql

Bu komutu shell’e yazarak modülü doğru kurup kurmadığımızı da kontrol edebiliriz. Şimdi, bağlantıyı sağlayacak bilgileri değişkenlerimize atayalım, böylece daha sonra değişiklik yapmak kolay olur. PHP ile çalıştıysanız config.php veya benzer isimlerdeki dosyaların sağladığı rahatlığı biliyorsunuzdur. Burda da amacımız bu. İsterseniz direk bağlantı fonksiyonuna bağlantı bilgilerini tabii ki yazabilirsiniz. Ama dediğim gibi, önerim bu şekilde kullanmanız.

host = "localhost" # Veritabanı host adresi
dbuser = "root" # Veritabanı kullanıcı adı
dbpass = "sifrem" # Veritabanı kullanıcı adının şifresi
db_adı = "veritabanim" # Veritabanı adı

Şimdi bu bilgileri bağlantı fonksiyonumuz olan connect() fonksiyonuna verelim. Modülümüzü kendi ismiyle import ettiğimiz için tahmin edeceğiniz üzere kullanımımız pymysql.connect() şeklinde olacak. Bunu bir değişkene atamamız gerekiyor.

self.bağlantı = pymysql.connect(host,dbuser,dbpass,db_adı)

Python3 ile çalıştığımız için değişken isimlerinde Türkçe karakter kullandığımızı da belirteyim. Onun dışında komutlarımız Python 2.x ile aynı. Şimdi, yaptığımız bağlantı üzerinde, tıpkı diğer mysql modüllerinde de olduğu gibi, bir imleç tanımlayalım. Daha önce bu tip bir bağlantı yapmadıysanız, bunun bir prosedür olduğunu bilmeniz yararlı olacaktır. Zira ben henüz bunu yapmadan kurulan bir bağlantıyla karşılaşmadım. Ayrıca bu tanımladığımız imleç, elde edeceğimiz sonuçları ayrıştırırken oldukça işe yarayacak. Şimdi, bu işlemi nasıl yapacağımızı görelim:

imleç = bağlantı.cursor()

Eğer PHP veya başka bir sistemle entegre çalışıyorsanız, birkaç denemeden sonra karakter sorunu yaşama ihtimaliniz var. Bununla ilgili internet üzerinde onlarca yöntem bulabilirsiniz. Ben baktıklarım arasında kesin bir yöntem bulamamakla birlikte, genel fikir hepsinin sırayla denenmesi yönünde. Zira tanımladığınız veritabanının karakter seti ve başka etkenler sebebiyle hangi yöntemin çalışacağını analiz etmek gerekiyor ki sanırım sırayla denemek daha kolay bir iş. Ben size benim bilgisayarımda sorunsuz çalışan bir tanesini aktaracağım. Bu MySQL komutunu PHP veya başka her neyle bağlanıyorsanız, imleç’inizi tanımladıktan hemen sonra vermeniz gerekiyor. MySQL sunucusuna yapılan tüm bağlantılar aynı karakter setinde olacağı için de(burada UTF-8 olarak atadık) sorun çıkma ihtimali oldukça azalıyor.

imleç.execute("SET NAMES 'utf8'")

Bunu PHP ile mysql_query() fonksiyonu yardımıyla da mysql_connect() in ardından verirseniz büyük ihtimalle probleminiz ortadan kalkacaktır.

Şimdi yolumuza devam edelim. Aslında, nasıl sorgulama yapacağımızla ilgili bariz bir örneği az önce gördük. Fonksiyonumuz, execute() fonksiyonu. Zaten Python altında exec adı verilen fonksiyon da verdiğiniz string i kod olarak işlemeye yarıyordu. Burda execute fonksiyonunun yaptığı iş de aynı. Verilen string’i mysql komutu olarak işliyor. Şimdi veritabanımızdan basit bir sorguyu nasıl yapacağımızı daha detaylı bir şekilde görelim:

var_mı = imleç.execute("select * from records where id1 = '{}' and id2 = '{}'".format(idler[0],idler[1]))
if var_mı:
    bulunan = imleç.fetchall()

Öncelikle, imleç.execute(KOMUT) yapısını kullanarak, records isimli tabloda id1 ve id2 değerleri verdiğimiz değerlere uygun olan verileri çekmek için bir komut verdik. id değerlerini idler isimli daha önceden tanımladığım bir listeden kullandım. İsterseniz idler = [1,4] diye düşünebilirsiniz. Burada, id değerleri integer(tamsayı) olmasına rağmen komutta ekstra olarak tek tırnak kullandığımıza dikkat edin. Bunu kullanmayınca sorun çıkabiliyor. Zaten elinizdeki bir string ise sorun çıkmaması için sebep kalmıyor. Bu komut, bize bir şey bulduysa doğru, bulmadıysa yanlış, yani boolean döndürür. Dolayısıyla sonucunu bir if yapısında kullanabiliriz. Sonucu var_mı isimli bir değişkene atıp, eğer sonuç bulunduysa bulunanların hepsini bulunan adlı değişkene atamasını söyledik. Bunu da cursor’un bir methodu olan fetchall() ile yaptık. fetchall’ın kullanımının imleç.fetchall şeklinde olduğuna dikkat etmekte yarar var.

Fetchall bize bulunan tüm sonuçları döndürür. Ama bulunan 1000 tane sonuç varsa hepsini almak gerekmeyebilir. Her birini sırayla almak istersek, ya da mesela 10 tane almak kalanını almamak istersek, ya da ilkini kullanmamız yetiyorsa(son eşleşme gibi) fetchone() methodu işimizi görüyor. imleç.fetchone() kodunu kullanarak bulunan ilk değeri, bunu tekrar çalıştırırsak 2. değeri … elimizdeki değerler bitene kadar bulabiliriz. Burada yapılacaklar sizin hayal gücünüze kalmış.

Bu işlemleri yaptıktan sonra, mysql bağlantısıyla işimiz bittiyse kapamamız gerekiyor. Bunun sebebini tam hatırlamamakla birlikte, açık bir bağlantı tutmanın pek faydalı olmayacağını söylemekte sakınca görmüyorum. İsterseniz bu modüllerin dökümanlarına bakıp neden kapatılması gerektiğini öğrenebilirsiniz. Kapatırken şöyle bir kod uyguluyoruz:

imleç.close()
bağlantı.close()

Son olarak, fetchall() ile verileri alıp ardından fetchone()’ı işleme koymaya çalışırsanız sorun çıkması doğaldır. Çünkü bu methodlar aldığı veriyi imleçten temizleyerek giderler. fetchone()’ın mantığı da bu şekilde olduğu için size her defasında ilk veriyi verir ve imleci bir sonraki sonuca kaydırır. fetchall() direk olarak imleci en sona kaydırdığı için yeni veri bulamazsınız.

 
comments powered by Disqus