10. Operação [IMPOTS] com MySQL
![]() |
10.1. Transferência de um arquivo de texto para uma tabela MySQL
O script a seguir irá transferir os dados do seguinte arquivo de texto:
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
para a tabela [impots] do banco de dados MySQL [dbimpots] a seguir:
![]() |
A conexão com o banco de dados [dbimpots] será feita com a identidade (root,"").
Utilizaremos a seguinte arquitetura:
![]() |
O script [console] que vamos escrever utilizará a classe [ImpotsFile] para acessar os dados do arquivo de texto. O acesso em gravação ao banco de dados será feito com os métodos vistos anteriormente.
O código do script é o seguinte:
# -*- coding=utf-8 -*-
# importação do módulo das classes de impostos
from impots import *
import re
# --------------------------------------------------------------------------
def copyToMysql(limites,coeffR,coeffN,HOTE,USER,PWD,BASE,TABLE):
# cópia as três tabelas numéricas de limites: coeffR, coeffN
# na tabela TABLE do banco de dados MySQL BASE
# o banco de dados MySQL está na máquina HOTE
# o usuário é identificado por USER e PWD
# colocamos as consultas SQL em uma lista
# exclusão da tabela
requetes=["drop table %s" % (TABLE)]
# criação da tabela
requete="create table %s (limites decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2))" % (TABLE)
requetes.append(requete)
# preenchimento
for i in range(len(limites)):
# consulta de inserção
requetes.append("insert into %s (limites,coeffR,coeffN) values (%s,%s,%s)" % (TABLE,limites[i],coeffR[i],coeffN[i]))
# executa-se os comandos SQL
return executerCommandes(HOTE,USER,PWD,BASE,requetes,False,False)
def executerCommandes(HOTE,ID,PWD,BASE,requetes,suivi=False,arret=True):
# utiliza a conexão (HOTE,ID,PWD,BASE)
# executa nessa conexão os comandos SQL contidos na lista de consultas
# se acompanhamento=True, então cada execução de um comando SQL é acompanhada por uma mensagem indicando se foi bem-sucedida ou falhou
# se parada=False, a função para ao encontrar o primeiro erro; caso contrário, ela executa todos os comandos SQL
# a função retorna uma lista (número de erros, erro1, erro2, ...)
# conexão
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)]
# solicita-se um cursor
curseur=connexion.cursor()
# execução das consultas SQL contidas na lista de consultas
# elas são executadas — inicialmente, sem erros
erreurs=[0]
for i in range(len(requetes)):
# a consulta é armazenada em uma variável local
requete=requetes[i]
# a consulta está vazia?
if re.match(r"^\s*$",requete):
continue
# execução da consulta i
erreur=""
try:
curseur.execute(requete)
except Exception, erreur:
pass
# houve algum erro?
if erreur:
# mais um erro
erreurs[0]+=1
# mensagem de erro
msg="%s : Erreur (%s)" % (requete[0:len(requete)-1],erreur)
erreurs.append(msg)
# exibir na tela ou não?
if suivi:
print msg
# paramos?
if arret:
return erreurs
else:
if suivi:
# exibimos a consulta sem o caractere de fim de linha
print "%s : Execution reussie" % (cutNewLineChar(requete))
# informações sobre o resultado da consulta executada
afficherInfos(curseur)
# encerramento da conexão
try:
connexion.commit()
connexion.close()
except MySQLdb.OperationalError,erreur:
# mais um erro
erreurs[0]+=1
# mensagem de erro
msg="%s : Erreur (%s)" % (requete,erreur)
erreurs.append(msg)
# retorno
return erreurs
# ------------------------------------------------ principal
# identidade do usuário
USER="root"
PWD=""
# o servidor do SGBD
HOTE="localhost"
# identidade do banco de dados
BASE="dbimpots"
# identidade da tabela de dados
TABLE="impots"
# o arquivo de dados
IMPOTS="impots.txt"
# instanciação da camada [dao]
try:
dao=ImpotsFile(IMPOTS)
except (IOError, ImpotsError) as infos:
print ("Une erreur s'est produite : {0}".format(infos))
sys.exit()
# os dados recuperados são transferidos para uma tabela do MySQL
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"
# fim
sys.exit()
Notas:
- linhas 106-110: instanciamos a classe [ImpotsFile] apresentada no parágrafo 8.1;
- linha 113: os tabuletos limites, coeffR e coeffN são transferidos para um tabuleto MySQL;
- linha 8: a função copyToMysql executa essa transferência. A função copyToMysql cria uma lista das consultas a serem executadas e as faz executar pela função executerCommandes, linha 25;
- linhas 28-89: a função executerCommandes é a mesma já apresentada anteriormente, no parágrafo 9.7, com uma diferença: em vez de estarem em um arquivo de texto, as consultas estão em uma lista;
O arquivo de texto impots.txt:
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
Resultados na tela:
Verificação com phpMyAdmin:
![]() |
10.2. O programa de cálculo do imposto
Agora que os dados necessários para o cálculo do imposto estão em um banco de dados, podemos escrever o script de cálculo do imposto. Utilizamos novamente uma arquitetura de três camadas:
![]() |
A nova camada [dao] será conectada às camadas SGBD e MySQL e será implementada pela classe [ImpotsMySQL]. Ela oferecerá à camada [metier] a mesma interface de antes, composta pelo único método getData, que retorna a tupla (limites, coeffR, coeffN). Assim, a camada [metier] não sofrerá alterações em relação à versão anterior.
10.3. A classe [ImpotsMySQL]
A camada [dao] agora é implementada pela seguinte classe [ImpotsMySQL] (arquivo impots.py):
class ImpotsMySQL:
# construtor
def __init__(self,HOTE,USER,PWD,BASE,TABLE):
# inicializa os atributos de limites, coeffR, coeffN
# os dados necessários para o cálculo do imposto foram inseridos na tabela mysqL TABLE
#, pertencente à base de dados BASE. A tabela possui a seguinte estrutura
# limites decimal(10,2), coeffR decimal(10,2), coeffN decimal(10,2)
# a conexão com o banco de dados MySQL da máquina HOTE é feita com a identidade (USER,PWD)
# lança uma exceção em caso de erro
# conexão com o banco de dados MySQL
connexion=MySQLdb.connect(host=HOTE,user=USER,passwd=PWD,db=BASE)
# solicita um cursor
curseur=connexion.cursor()
# leitura em bloco da tabela TABLE
requete="select limites,coeffR,coeffN from %s" % (TABLE)
# executa a consulta [requete] no banco de dados [base] da conexão [connexion]
curseur.execute(requete)
# análise do resultado da consulta
ligne=curseur.fetchone()
self.limites=[]
self.coeffR=[]
self.coeffN=[]
while(ligne):
# linha atual
self.limites.append(ligne[0])
self.coeffR.append(ligne[1])
self.coeffN.append(ligne[2])
# linha seguinte
ligne=curseur.fetchone()
# desconexão
connexion.close()
def getData(self):
return (self.limites, self.coeffR, self.coeffN)
Observações:
- linha 18: a consulta SQL SELECT que solicita os dados do banco de dados MySQL. As linhas de resultados da consulta SELECT são, em seguida, processadas uma a uma pela consulta [curseur.fetchone] (linhas 22 e 32) para criar as tabelas limites, coeffR e coeffN (linhas 28-30);
- o método getData da interface da camada [dao].
10.4. O script de console
O código do script de console (impots_04) é o seguinte:
# -*- coding=utf-8 -*-
# importação do módulo das classes Impostos*
from impots import *
# ------------------------------------------------ main
# identidade do usuário
USER="root"
PWD=""
# o servidor do SGBD
HOTE="localhost"
# identidade do banco de dados
BASE="dbimpots"
# identidade da tabela de dados
TABLE="impots"
# arquivo de entrada
DATA="data.txt"
# arquivo de saída
RESULTATS="resultats.txt"
# instância da camada [metier]
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()
# os dados necessários para o cálculo do imposto foram inseridos no arquivo IMPOTS
# à razão de uma linha por tabela, na forma
# val1:val2:val3,...
# leitura dos dados
try:
data=open(DATA,"r")
except:
print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
sys.exit()
# abertura do arquivo de resultados
try:
resultats=open(RESULTATS,"w")
except:
print "Impossible de creer le fichier des résultats [RESULTATS]"
sys.exit()
# utilitários
u=Utilitaires()
# processa-se a linha atual do arquivo de dados
ligne=data.readline()
while(ligne != ''):
# remove-se o eventual caractere de fim de linha
ligne=u.cutNewLineChar(ligne)
# recupera-se os três campos “casado:filhos:salário” que compõem a linha
(marie,enfants,salaire)=ligne.split(",")
enfants=int(enfants)
salaire=int(salaire)
# calcula-se o imposto
impot=metier.calculer(marie,enfants,salaire)
# registra-se o resultado
resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
# lê-se uma nova linha
ligne=data.readline()
# fecha-se os arquivos
data.close()
resultats.close()
Notas:
- linha 23: instanciação das camadas [dao] e [metier];
- o restante do código já é conhecido.
Os mesmos das versões anteriores do exercício.



