Skip to content

10. [IMPOTS] alıştırması, MySQL ile birlikte

10.1. Bir metin dosyasının bir tabloya aktarılması MySQL

Aşağıdaki metin dosyasındaki verileri aktaracak olan komut dosyası:

12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:272.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062

aşağıdaki MySQL [dbimpots] veritabanındaki [impots] tablosuna aktaracaktır:

 

[dbimpots] veritabanına, (root,"") kimlik bilgileriyle bağlanılacaktır.


Program (impotstxt2mysql)

Aşağıdaki mimariyi kullanacağız:

Yazacağımız [console] komut dosyası, metin dosyasındaki verilere erişmek için [ImpotsFile] sınıfını kullanacaktır. Veritabanına yazma erişimi, daha önce gördüğümüz yöntemlerle sağlanacaktır.

Komut dosyasının kodu şöyledir:


# -*- coding=utf-8 -*-

# Vergi sınıfları modülünün içe aktarılması
from impots import *
import re

# --------------------------------------------------------------------------
def copyToMysql(limites,coeffR,coeffN,HOTE,USER,PWD,BASE,TABLE):
    # 3 sınır değer tablosunu kopyalar: coeffR, coeffN
    # mysql veritabanındaki TABLE tablosuna BASE
    # mysql veritabanı HOTE makinesinde bulunuyor
    # kullanıcı, USER ve PWD ile tanımlanıyor

    # SQL sorguları bir listeye eklenir
    # tablonun silinmesi
    requetes=["drop table %s" % (TABLE)]
    # tablonun oluşturulması
    requete="create table %s (limites decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2))" % (TABLE)
    requetes.append(requete)
    # verilerin girilmesi
    for i in range(len(limites)):
        # ekleme sorgusu
        requetes.append("insert into %s (limites,coeffR,coeffN) values (%s,%s,%s)" % (TABLE,limites[i],coeffR[i],coeffN[i]))
    # SQL komutları yürütülüyor
    return executerCommandes(HOTE,USER,PWD,BASE,requetes,False,False)
    

def executerCommandes(HOTE,ID,PWD,BASE,requetes,suivi=False,arret=True):
    # bağlantıyı kullan (HOTE,ID,PWD,BASE)
    # istek listesinde bulunan SQL komutlarını bu bağlantı üzerinden yürütür
    # takip=True ise, her bir SQL komutunun yürütülmesi, komutun başarılı veya başarısız olduğunu belirten bir mesajın görüntülenmesine neden olur
    # durdurma=False ise, işlev karşılaşılan ilk hatada durur; aksi takdirde tüm SQL komutlarını yürütür
    # fonksiyon bir liste döndürür (hata sayısı, hata1, hata2, ...)

    # bağlantı
    try:
        connexion=MySQLdb.connect(host=HOTE,user=ID,passwd=PWD,db=BASE)
    except MySQLdb.OperationalError,erreur:
        return [1,"Erreur lors de la connexion a MySQL sous l'identite (%s,%s,%s,%s) : %s" % (HOTE, ID, PWD, BASE, erreur)]
      
    # bir imleç talep edilir
    curseur=connexion.cursor()
    # sorgu listesinde yer alan SQL sorgularının yürütülmesi
    # yürütülüyor - başlangıçta hata yok
    erreurs=[0]
    for i in range(len(requetes)):
        # sorgu yerel bir değişkene atanıyor
        requete=requetes[i]
        # Sorgu boş mu?
        if re.match(r"^\s*$",requete):
            continue
        # i isteğinin yürütülmesi
        erreur=""
        try:
            curseur.execute(requete)
        except Exception, erreur:
            pass
        # Bir hata oluştu mu?
        if erreur:
            # bir hata daha
            erreurs[0]+=1
            # hata mesajı
            msg="%s : Erreur (%s)" % (requete[0:len(requete)-1],erreur)
            erreurs.append(msg)
            # ekran izleme var mı, yok mu?
            if suivi:
                print msg
            # durulacak mı?
            if arret:
                return erreurs
        else:
            if suivi: 
                # satır sonu işaretini içermeyen sorgu görüntüleniyor
                print "%s : Execution reussie" % (cutNewLineChar(requete))
                # çalıştırılan sorgunun sonucuna ilişkin bilgiler
                afficherInfos(curseur)
    # bağlantıyı kapat
    try:
        connexion.commit()
        connexion.close()
    except MySQLdb.OperationalError,erreur:
        # bir hata daha
        erreurs[0]+=1
        # hata mesajı
        msg="%s : Erreur (%s)" % (requete,erreur)
        erreurs.append(msg)

    # geri dönüş
    return erreurs


# ------------------------------------------------ ana sayfa
# kullanıcı kimliği
USER="root"
PWD=""
# veritabanı yönetim sisteminin ana bilgisayarı
HOTE="localhost"
# veritabanı kimliği
BASE="dbimpots"
# veri tablosunun kimliği
TABLE="impots"
# veri dosyası
IMPOTS="impots.txt"

# [dao] katmanının örneği
try:
    dao=ImpotsFile(IMPOTS)
except (IOError, ImpotsError) as infos:
    print ("Une erreur s'est produite : {0}".format(infos))
    sys.exit()

# alınan veriler bir MySQL tablosuna aktarılır
erreurs=copyToMysql(dao.limites,dao.coeffR,dao.coeffN,HOTE,USER,PWD,BASE,TABLE)
if erreurs[0]:
    for i in range(1,len(erreurs)):
        print erreurs[i]
else:
    print "Transfert opere"
# son
sys.exit()

Notlar:

  • 106-110. satırlar: 8.1. paragrafta tanıtılan [ImpotsFile] sınıfı örneklenir;
    1. satır: limites, coeffR ve coeffN tabloları, MySQL veritabanına aktarılır;
  • satır 8: copyToMysql fonksiyonu bu aktarımı gerçekleştirir. copyToMysql fonksiyonu, yürütülecek sorguların bir tablosunu oluşturur ve bunları 25. satırdaki executerCommandes fonksiyonu aracılığıyla yürütür;
  • satır 28-89: executerCommandes işlevi, daha önce 9.7. paragrafta sunulan işlevin aynısıdır, tek fark şudur: sorgular bir metin dosyasında değil, bir listede yer almaktadır;

Sonuçlar

impots.txt metin dosyası:

12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:272.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062

Ekran sonuçları:

Transfert opéré

phpMyAdmin ile doğrulama:

 

10.2. Vergi hesaplama programı

Vergi hesaplaması için gerekli veriler artık bir veritabanında bulunduğuna göre, vergi hesaplama komut dosyasını yazabiliriz. Yine üç katmanlı bir mimari kullanıyoruz:

Yeni [dao] katmanı, SGBD ve MySQL katmanlarına bağlanacak ve [ImpotsMySQL] sınıfı tarafından uygulanacaktır. Bu katman, [metier] katmanına, daha önce olduğu gibi, (sınırlar, coeffR, coeffN) tuple'ını döndüren tek yöntem olan getData'ten oluşan aynı arayüzü sunacaktır. Böylece [metier] katmanı, önceki sürüme göre değişmeyecektir.

10.3. [ImpotsMySQL] sınıfı

[dao] katmanı artık aşağıdaki [ImpotsMySQL] sınıfı tarafından uygulanmaktadır (impots.py dosyası):


class ImpotsMySQL:

    # oluşturucu
    def __init__(self,HOTE,USER,PWD,BASE,TABLE):
        # sınır özniteliklerini başlatır: coeffR, coeffN
        # Vergi hesaplaması için gerekli veriler, mysqL TABLE
        # tablosuna eklenmiştir. Bu tablo, BASE veritabanına aittir. Tablonun yapısı aşağıdaki gibidir
        # sınırlar decimal(10,2), coeffR decimal(10,2), coeffN decimal(10,2)
        # HOTE makinesindeki MySQL veritabanına (USER,PWD) kimlik bilgileriyle bağlanılır
        # olası bir hata durumunda istisna oluşturur
        
        # MySQL veritabanına bağlantı kurulur
        connexion=MySQLdb.connect(host=HOTE,user=USER,passwd=PWD,db=BASE)
        # bir imleç talep edilir
        curseur=connexion.cursor()
        
        # TABLE tablosundan toplu okuma
        requete="select limites,coeffR,coeffN from %s" % (TABLE)
        # [requete] sorgusunu, [connexion] bağlantısının [base] veritabanında yürütür
        curseur.execute(requete)
        # sorgu sonucunun işlenmesi
        ligne=curseur.fetchone()
        self.limites=[]
        self.coeffR=[]
        self.coeffN=[]
        while(ligne):
            # geçerli satır
            self.limites.append(ligne[0])
            self.coeffR.append(ligne[1])
            self.coeffN.append(ligne[2])
            # sonraki satır
            ligne=curseur.fetchone()
        # oturum kapatma
        connexion.close()

    def getData(self):
        return (self.limites, self.coeffR, self.coeffN)

Notlar:

    1. satır: SQL SELECT sorgusu, MySQL veritabanındaki verileri ister. SELECT sorgusunun sonuç satırları daha sonra [curseur.fetchone] tarafından tek tek işlenir (22. ve 32. satırlar) ve limites, coeffR ve coeffN tabloları oluşturulur (satır 28-30);
  • [dao] katman arayüzünün getData yöntemi.

10.4. Konsol komut dosyası

Konsol komut dosyasının kodu (impots_04) şöyledir:


# -*- coding=utf-8 -*-

# Impots* sınıfları modülünün içe aktarılması
from impots import *

# ------------------------------------------------ ana işlev
# kullanıcı kimliği
USER="root"
PWD=""
# veritabanı yönetim sisteminin ana bilgisayarı
HOTE="localhost"
# veritabanının kimliği
BASE="dbimpots"
# veri tablosunun kimliği
TABLE="impots"
# giriş dosyası
DATA="data.txt"
# çıktı dosyası
RESULTATS="resultats.txt"

# [metier] katmanının örneği
try:
    metier=ImpotsMetier(ImpotsMySQL(HOTE,USER,PWD,BASE,TABLE))
except (IOError, ImpotsError) as infos:
    print ("Une erreur s'est produite : {0}".format(infos))
    sys.exit()

# vergi hesaplaması için gerekli veriler IMPOTS dosyasına yerleştirilmiştir
# tablolar için her bir satırda şu biçimde
# val1:val2:val3,...

# verilerin okunması
try:
    data=open(DATA,"r")
except:
    print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
    sys.exit()

# sonuç dosyasının açılması
try:
    resultats=open(RESULTATS,"w")
except:  
    print "Impossible de creer le fichier des résultats [RESULTATS]"
    sys.exit()

# yardımcı programlar
u=Utilitaires()

# veri dosyasının geçerli satırını işliyoruz
ligne=data.readline()
while(ligne != ''):
    # varsa satır sonu işaretini kaldırma
    ligne=u.cutNewLineChar(ligne)
    # satırı oluşturan "evli:çocuk sayısı:maaş" şeklindeki 3 alanı alınır
    (marie,enfants,salaire)=ligne.split(",")
    enfants=int(enfants)
    salaire=int(salaire)
    # vergi hesaplanır
    impot=metier.calculer(marie,enfants,salaire)
    # sonuç yazılır
    resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
    # yeni bir satır okunur
    ligne=data.readline()
# dosyaları kapatıyoruz
data.close()
resultats.close()

Notlar:

    1. satır: [dao] ve [metier] katmanlarının örneklenmesi;
  • kodun geri kalanı biliniyor.

Sonuçlar

Alıştırmanın önceki sürümleriyle aynıdır.