Introdução A Classes e Métodos em Python
Introdução A Classes e Métodos em Python
Introdução A Classes e Métodos em Python
Python (básico)
// Tags python classes métodos
Eu não sou a melhor pessoa do mundo para explicar este assunto, mas eu escrevi este
post para introduzir um tópico sobre manipulação de banco de dados em SQLite3 com
Python, porém mais informações sobre classes e métodos podem ser encontradas nos
links abaixo. Veja os exemplos em https://github.com/rg3915/pythonDesktopApp.
Segundo a documentação do Python e o video Python para Zumbis, uma classe associa
dados (atributos) e operações (métodos) numa só estrutura. Um objeto é uma variável
cujo tipo é uma classe, ou seja, um objeto é uma instância de uma classe.
class NomeDaClasse(object):
pass
def metodo(args):
pass
onde args são argumentos opcionais (parâmetros de entrada). A função metodo pode
retornar um valor de saída:
def metodo(args):
return args
class NomeDaClasse(object):
atributo1 = None
A primeira pergunta que você vai ter é o porque do self em metodo. A resposta curta é,
todo metodo criado dentro de uma classe deve definir como primeiro parametro o self.
Para a resposta longa, por favor, leia a excelente explicação que o Pedro Werneck fez:
http://www.pedrowerneck.com/o-porque-do-self-explicito-em-python-pt-br.html
1
o caractere :. Devido a esse fato, python necessitava de algo para explicitar quando se
quer definir um bloco vazio. O pass foi criado exatamente para explicitar essa situação.
Um exemplo de uma função vazia feita em linguagem C e a mesma função vazia feita
em Python:
}
def metodo(num):
pass
#calculadora.py
class Calculadora(object):
def soma(self):
return self.a + self.b
def subtrai(self):
return self.a - self.b
def multiplica(self):
return self.a * self.b
def divide(self):
return self.a / self.b
Poderíamos definir
2
self.a = param1
self.b = param2
para não confundir, mas usualmente usamos o mesmo nome tanto no parâmetro quanto
no novo campo.
Como dito antes, definimos os valores iniciais apenas uma vez e depois apenas usamos
os métodos para calcular os valores.
Podemos rodar o Python no modo modo interativo pelo terminal e importar a classe
(veja este video).
$ python3
>>> from calculadora import Calculadora
>>> c = Calculadora(128,2)
>>> print('Soma:', c.soma())
>>> print('Subtração:', c.subtrai())
>>> print('Multiplicação:', c.multiplica())
>>> print('Divisão:', c.divide())
O resultado é:
>>> c.a = 12
>>> c.b = 42
>>> print c.soma()
Resultado:
>>> 54
Importante: apesar de não fazer parte do escopo deste artigo, mas vejam este video
Operadores aritméticos e divisão no Python 2 e Python 3, explicando sobre a diferença
no resultado da divisão nas duas versões do Python.
Vejam também este artigo sobre ponto flutuante: Floating Point Arithmetic Issues and
Limitations.
Exemplo 2 - Calculadora
Agora faremos uma classe sem valor inicial e com dois parâmetros para todos os
métodos.
#calculadora2.py
class Calculadora(object):
3
def soma(self, a, b):
return a + b
$ python3
>>> from calculadora2 import Calculadora
>>> c = Calculadora()
>>> print('Soma:', c.soma(2,3))
>>> print('Subtração:', c.subtrai(2,10))
>>> print('Multiplicação:', c.multiplica(3,3))
>>> print('Divisão:', c.divide(128,2))
#user.py
class User(object):
seq = 0
objects = []
def save(self):
self.__class__.seq += 1
self.id = self.__class__.seq
self.__class__.objects.append(self)
def __str__(self):
return self.nome
def __repr__(self):
return '<{}: {} - {} - {}>\n'.format(self.__class__.__name__,
self.id, self.nome, self.idade)
4
@classmethod
def all(cls):
return cls.objects
if __name__ == '__main__':
u1 = User('Regis', 35)
u1.save()
u2 = User('Fabio', 20)
u2.save()
print(User.all())
Podemos rodar o Python no modo modo interativo pelo terminal e importar a classe
(veja este video).
$ python3
>>> from user import User
>>> u1 = User('Regis', 35)
>>> u1.save()
>>> u2 = User('Fabio',20)
>>> u2.save()
>>> print(User.all())
Agora os comentários:
Definindo a classe
class User(object):
Define um atributo que servirá como contador inicial e um atributo objects (tupla
vazia) que é uma lista de instâncias de User que foram salvos (que chamaram o método
save).
seq = 0
objects = []
Inicializando os atributos, id começa com None, pois a instância foi criada mas ainda
não foi salva.
self.id = None
self.nome = nome
self.idade = idade
Método para salvar os dados ele incrementa o atributo de classe que conta quantas
instâncias foram salvas e adiciona a instância na lista de objects.
def save(self):
5
self.__class__.seq += 1
self.id = self.__class__.seq
Da mesma forma que acessamos seq, acessamos objects e é feito um append com a
instância.
self.__class__.objects.append(self)
Retorna uma representação do objeto como str, usado em conversões para string.
Exemplo: str(my_user), print my_user.
def __str__(self):
return self.nome
Retorna uma representação do objeto usada para outros objetos. Exemplo: quando é
convertida uma lista de user para string.
def __repr__(self):
Class method usado para acessar todas as instâncias salvas (que chamaram o método
save). Aqui usamos um @classmethod, pois faz mais sentido ser um método de classe
do que de instância, pois estamos retornando informações da classe e não de uma
instância isolada.
@classmethod
def all(cls):
return cls.objects
if __name__ == '__main__':
u1 = User('Regis', 35)
u2 = User('Fabio',20)
print(User.all())
u1.save()
u2.save()
print(User.all())
Após chamar o save para as duas instâncias elas são guardadas e o método User.all()
retorna essa lista.
6
Guia rápido de comandos SQLite3
// Tags sqlite
É sempre bom ter tudo que você precisa de forma rápida e simples.
CRUD
Backup
Relacionando tabelas
$ sqlite3 Clientes.db
2. A Ajuda.
sqlite> .help
sqlite> .table
7
6. Saindo do SQLite3.
sqlite> .exit
CRUD
Abra um editor de texto e salve um arquivo com o nome inserirdados.sql.
$ gedit inserirdados.sql
Nota: No caso do INSERT INTO não precisamos numerar, basta trocar o número do id
por NULL, exemplo:
$ sqlite3 Clientes.db
sqlite> SELECT * FROM clientes;
sqlite> .header on
8
12. Visualizando as colunas da tabela clientes.
Cuidado: se você não usar o WHERE e escolher um id você pode deletar todos os
registros da tabela.
Backup
$ sqlite3 Clientes.db .dump > clientes.sql
$ cat clientes.sql
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE clientes(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
Nome VARCHAR(100) NOT NULL,
CPF VARCHAR(11) NOT NULL,
Email VARCHAR(20) NOT NULL,
Fone VARCHAR(20),
UF VARCHAR(2) NOT NULL
);
INSERT INTO "clientes"
VALUES(1,'Regis','00000000000','[email protected]','1100000000','SP');
INSERT INTO "clientes"
VALUES(2,'Abigail','11111111111','[email protected]','1112345678','RJ'
);
INSERT INTO "clientes"
VALUES(3,'Benedito','22222222222','[email protected]','1187654321','S
P');
INSERT INTO "clientes"
VALUES(4,'Zacarias','33333333333','[email protected]','1199999999','R
J');
COMMIT;
$ mv Clientes.db Clientes.db.old
9
$ sqlite3 Clientes_recuperado.db < clientes.sql
$ sqlite3 Clientes_recuperado.db 'SELECT * FROM clientes;'
Relacionando tabelas
Todos devem saber que num banco de dados relacional a chave estrangeira ou
FOREIGN KEY tem um papel importante no relacionamento entre duas tabelas. Veremos
aqui como relacionar duas tabelas.
$ sqlite3 Clientes.db
sqlite> .tables
clientes
sqlite> .header on
sqlite> .mode column
10
Segundo Sqlite Drop Column, não tem como "deletar" uma coluna, então precisamos
criar uma nova tabela clientes_novo com os campos que precisamos e copiar os dados
da primeira tabela para esta.
Agora você terá que popular as cidades e definir a cidade_id em cada cliente.
Lembrando que a chave é AUTOINCREMENT, então use NULL.
Resultado.
11
id Nome CPF Email Fone
bloqueado cidade_id
---------- ---------- ----------- ------------ ---------- -------
--- ----------
1 Regis 00000000000 [email protected] 1100000000 1
3
2 Abigail 11111111111 abigail@emai 1112345678 1
1
3 Benedito 22222222222 benedito@ema 1187654321 0
2
Façamos um INNER JOIN para visualizar todos os dados, inclusive a cidade e o uf.
12
Gerenciando banco de dados SQLite3
com Python - Parte 1
// Tags Python Banco de dados
Eu separei este post em duas partes: a Parte 1 é bem elementar e objetiva, visando
apresentar o básico sobre a realização do CRUD num banco de dados SQLite3 em
Python usando o terminal.
A parte 2 , num nível intermediário, usa classes e métodos mais elaborados para
gerenciar o CRUD, e algumas coisinhas a mais.
Nota: Para entender o uso de classes e métodos leia o post Introdução a Classes e
Métodos em Python. E para entender os comandos SQL e a manipulação de registros no
SQLite3 leia Guia rápido de comandos SQLite3.
id inteiro sim
Obs: O campo bloqueado nós vamos inserir depois com o comando ALTER TABLE.
13
Como mencionado antes, esta parte será básica e objetiva. A intenção é realizar o
CRUD da forma mais simples e objetiva possível.
Exemplos
Referências
# conectando...
conn = sqlite3.connect(':memory:')
# conectando...
conn = sqlite3.connect('clientes.db')
# connect_db.py
14
# 01_create_db.py
import sqlite3
conn = sqlite3.connect('clientes.db')
conn.close()
$ python3 01_create_db.py
$ ls *.db
# 02_create_schema.py
import sqlite3
# conectando...
conn = sqlite3.connect('clientes.db')
# definindo um cursor
cursor = conn.cursor()
15
conn.close()
$ python3 02_create_schema.py
$ sqlite3 clientes.db '.tables'
$ sqlite3 clientes.db 'PRAGMA table_info(clientes)'
Digitando sqlite3 clientes.db '.tables' você verá que a tabela foi criada.
Nota: A única diferença, caso você use Python 2 é no print, onde você deve tirar os
parênteses. E no início do arquivo é recomendável que se defina a codificação utf-8,
que no caso do Python 3 já é padrão.
# 02_create_schema.py
# -*- coding: utf-8 -*-
# usando Python 2
import sqlite3
...
print 'Tabela criada com sucesso.'
# 03_create_data_sql.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
cursor.execute("""
INSERT INTO clientes (nome, idade, cpf, email, fone, cidade, uf,
criado_em)
VALUES ('Aloisio', 87, '11111111111', '[email protected]', '98765-
4322', 'Porto Alegre', 'RS', '2014-06-09')
""")
cursor.execute("""
INSERT INTO clientes (nome, idade, cpf, email, fone, cidade, uf,
criado_em)
16
VALUES ('Bruna', 21, '22222222222', '[email protected]', '21-98765-
4323', 'Rio de Janeiro', 'RJ', '2014-06-09')
""")
cursor.execute("""
INSERT INTO clientes (nome, idade, cpf, email, fone, cidade, uf,
criado_em)
VALUES ('Matheus', 19, '33333333333', '[email protected]', '11-98765-
4324', 'Campinas', 'SP', '2014-06-08')
""")
# gravando no bd
conn.commit()
conn.close()
$ python3 03_create_data_sql.py
# 04_create_data_nrecords.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
conn.commit()
conn.close()
Observe o uso de ? isto significa que no lugar de cada ? entrará os valores da lista na
sua posição respectiva. É o que nós chamamos de parâmetros de entrada.
17
Para executar digite no terminal:
$ python3 04_create_data_nrecords.py
# 05_create_data_param.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
conn.commit()
conn.close()
# python 2
p_nome = raw_input('Nome: ')
...
print 'Dados inseridos com sucesso.'
$ python3 05_create_data_param.py
Nome: Regis
Idade: 35
18
CPF: 30020030011
Email: [email protected]
Fone: 11 9537-0000
Cidade: Sao Paulo
UF: SP
Criado em (yyyy-mm-dd): 2014-06-15
Dados inseridos com sucesso.
# 06_read_data.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
# lendo os dados
cursor.execute("""
SELECT * FROM clientes;
""")
conn.close()
$ python3 06_read_data.py
Eis o resultado:
19
Observe o uso das variáveis id_cliente onde definimos o id a ser alterado,
novo_fone e novo_criado_em usados como parâmetro para alterar os dados. Neste
caso, salvamos as alterações com o método commit().
# 07_update_data.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
id_cliente = 1
novo_fone = '11-1000-2014'
novo_criado_em = '2014-06-11'
conn.commit()
conn.close()
$ python3 07_update_data.py
# 08_delete_data.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
id_cliente = 8
conn.commit()
conn.close()
20
$ python3 08_delete_data.py
# 09_alter_table.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
conn.commit()
conn.close()
$ python3 09_alter_table.py
Para listar as tabelas do banco usamos o comando SELECT name FROM sqlite_master
....
Para ler o schema da tabela usamos o comando SELECT sql FROM sqlite_master
....
# 10_view_table_info.py
import sqlite3
conn = sqlite3.connect('clientes.db')
cursor = conn.cursor()
nome_tabela = 'clientes'
# listando as tabelas do bd
cursor.execute("""
21
SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
""")
print('Tabelas:')
for tabela in cursor.fetchall():
print("%s" % (tabela))
print('Schema:')
for schema in cursor.fetchall():
print("%s" % (schema))
conn.close()
$ python3 10_view_table_info.py
Eis o resultado:
# 11_backup.py
import sqlite3
import io
conn = sqlite3.connect('clientes.db')
22
f.write('%s\n' % linha)
conn.close()
$ python3 11_backup.py
$ cat clientes_dump.sql
# 12_read_sql.py
import sqlite3
import io
conn = sqlite3.connect('clientes_recuperado.db')
cursor = conn.cursor()
f = io.open('clientes_dump.sql', 'r')
sql = f.read()
cursor.executescript(sql)
conn.close()
$ python3 12_read_sql.py
Banco de dados recuperado com sucesso.
Salvo como clientes_recuperado.db
$ sqlite3 clientes_recuperado.db 'SELECT * FROM clientes;'
Com o último comando você verá que os dados estão lá. São e salvo!!!
Leia a continuação deste artigo em Gerenciando banco de dados SQLite3 com Python -
Parte 2.
23
Gerenciando banco de dados SQLite3
com Python - Parte 2
// Tags Python Banco de dados
Esta é a continuação do artigo Gerenciando banco de dados SQLite3 com Python - Parte
1. Naa 1ª parte nós vimos como realizar o CRUD num banco de dados SQLite3 usando o
Python, mas cada tarefa foi feita num arquivo .py separado. A intenção agora é utilizar
um único arquivo e, usando classes e métodos realizar as mesmas tarefas, só que de
uma formama mais sofisticada.
Também fiz uma série de videos, assista a primeira aula abaixo ou acesse todas as aulas no
YouTube.
id inteiro sim
Obs: O campo bloqueado nós vamos inserir depois com o comando ALTER TABLE.
24
PS: Considere a sintaxe para Python 3. Mas o programa roda em python2 também.
Preparando o terreno
Modo interativo
Mais SELECT
SELECT personalizado
25
Exemplos
Referências
Preparando o terreno
Neste artigo eu usei os pacotes names e rstr , o primeiro gera nomes randômicos e o
segundo gera string e números randômicos. No meu SO estou usando o Python 3.4, mas
para não ter problemas com os pacotes eu criei um ambiente virtual.
Obs: Se você estiver usando Python 3 ou Python 2x não é obrigado a usar virtualenv
mas mesmo assim precisará instalar os pacotes names e rstr.
$ virtualenv python-sqlite
Habilite o python3
Vá para a pasta
$ cd python-sqlite
Ative o ambiente
$ source bin/activate
(python-sqlite)~/git/python-sqlite$
Instale as dependências
Entre na pasta
$ cd intermediario
26
Agora vamos diminuir o caminho do prompt
(python-sqlite):/intermediario$
# gen_random_values.py
import random
import rstr
import datetime
Vamos criar uma função gen_age() para gerar um número inteiro entre 15 e 99 usando
o comando random.randint(a,b) .
def gen_age():
return random.randint(15, 99)
A função gen_cpf() gera uma string com 11 caracteres numéricos. No caso, o primeiro
parâmetro são os caracteres que serão sorteados e o segundo é o tamanho da string.
def gen_cpf():
return rstr.rstr('1234567890', 11)
Agora vamos gerar um telefone com a função gen_phone() no formato (xx) xxxx-xxxx
def gen_phone():
return '({0}) {1}-{2}'.format(
rstr.rstr('1234567890', 2),
rstr.rstr('1234567890', 4),
rstr.rstr('1234567890', 4))
def gen_timestamp():
27
year = random.randint(1980, 2015)
month = random.randint(1, 12)
day = random.randint(1, 28)
hour = random.randint(1, 23)
minute = random.randint(1, 59)
second = random.randint(1, 59)
microsecond = random.randint(1, 999999)
date = datetime.datetime(
year, month, day, hour, minute, second,
microsecond).isoformat(" ")
return date
def gen_city():
list_city = [
[u'São Paulo', 'SP'],
[u'Rio de Janeiro', 'RJ'],
[u'Porto Alegre', 'RS'],
[u'Campo Grande', 'MS']]
return random.choice(list_city)
# connect_db.py
import sqlite3
class Connect(object):
28
O próximo passo é fechar a conexão com o banco:
def close_db(self):
if self.conn:
self.conn.close()
print("Conexão fechada.")
class ClientesDb(object):
def __init__(self):
self.db = Connect('clientes.db')
def close_connection(self):
self.db.close_db()
Fazendo desta forma é possível instanciar outras classes, uma para cada banco, como
PessoasDb() que veremos mais pra frente.
if __name__ == '__main__':
cliente = ClientesDb()
cliente.close_connection()
$ python3 connect_db.py
$ ls *.db
Modo interativo
Legal mesmo é quando usamos o modo interativo para rodar os comandos do python,
para isso podemos usar o python3 ou ipython3. No terminal basta digitar python3 ENTER
que vai aparecer o prompt abaixo (na mesma pasta do projeto, tá?)
$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:18)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
29
>>> db.close_db()
>>> exit()
Mas vou repetir o código inicial para criar e conectar o banco de dados:
# manager_db.py
import os
import sqlite3
import io
import datetime
import names
import csv
from gen_random_values import *
class Connect(object):
def commit_db(self):
if self.conn:
self.conn.commit()
def close_db(self):
if self.conn:
30
self.conn.close()
print("Conexão fechada.")
class ClientesDb(object):
tb_name = 'clientes'
def __init__(self):
self.db = Connect('clientes.db')
self.tb_name
def fechar_conexao(self):
self.db.close_db()
if __name__ == '__main__':
c = ClientesDb()
Rodando no terminal...
$ python3 manager_db.py
$ ls *.db
Ou no modo interativo...
$ python3
>>> from manager_db import *
>>> c = ClientesDb()
Banco: clientes.db
SQLite version: 3.8.2
>>> exit()
try:
with open(schema_name, 'rt') as f:
schema = f.read()
self.db.cursor.executescript(schema)
except sqlite3.Error:
print("Aviso: A tabela %s já existe." % self.tb_name)
return False
...
if __name__ == '__main__':
c = ClientesDb()
c.criar_schema()
31
Aqui nós criamos a função criar_schema(self, schema_name) dentro da classe
ClientesDb().
Modo interativo...
$ python3
>>> from manager_db import *
>>> c = ClientesDb()
>>> c.criar_schema()
Criando tabela clientes ...
Tabela clientes criada com sucesso.
def inserir_um_registro(self):
try:
self.db.cursor.execute("""
INSERT INTO clientes (nome, idade, cpf, email, fone, cidade,
uf, criado_em)
VALUES ('Regis da Silva', 35, '12345678901',
'[email protected]', '(11) 9876-5342',
'São Paulo', 'SP', '2014-07-30 11:23:00.199000')
""")
# gravando no bd
self.db.commit_db()
print("Um registro inserido com sucesso.")
except sqlite3.IntegrityError:
print("Aviso: O email deve ser único.")
return False
...
if __name__ == '__main__':
c = ClientesDb()
c.criar_schema()
c.inserir_um_registro()
32
A função a seguir insere vários registros a partir de uma lista. Repare no uso do
comando executemany(sql, [parâmetros])
que executa a instrução sql várias vezes. Note também, pela sintaxe, que a quantidade
de ? deve ser igual a quantidade de campos, e o parâmetro, no caso está sendo a lista
criada.
def inserir_com_lista(self):
# criando uma lista de dados
lista = [('Agenor de Sousa', 23, '12345678901',
'[email protected]',
'(10) 8300-0000', 'Salvador', 'BA', '2014-07-29
11:23:01.199001'),
('Bianca Antunes', 21, '12345678902', '[email protected]',
'(10) 8350-0001', 'Fortaleza', 'CE', '2014-07-28
11:23:02.199002'),
('Carla Ribeiro', 30, '12345678903', '[email protected]',
'(10) 8377-0002', 'Campinas', 'SP', '2014-07-28
11:23:03.199003'),
('Fabiana de Almeida', 25, '12345678904',
'[email protected]',
'(10) 8388-0003', 'São Paulo', 'SP', '2014-07-29
11:23:04.199004'),
]
try:
self.db.cursor.executemany("""
INSERT INTO clientes (nome, idade, cpf, email, fone, cidade,
uf, criado_em)
VALUES (?,?,?,?,?,?,?,?)
""", lista)
# gravando no bd
self.db.commit_db()
print("Dados inseridos da lista com sucesso: %s registros." %
len(lista))
except sqlite3.IntegrityError:
print("Aviso: O email deve ser único.")
return False
def inserir_de_arquivo(self):
try:
with open('sql/clientes_dados.sql', 'rt') as f:
dados = f.read()
self.db.cursor.executescript(dados)
# gravando no bd
self.db.commit_db()
print("Dados inseridos do arquivo com sucesso.")
except sqlite3.IntegrityError:
print("Aviso: O email deve ser único.")
33
return False
import csv
...
Obs: Veja em gen_csv.py como podemos gerar dados randômicos para criar um novo
clientes.csv.
def inserir_com_parametros(self):
# solicitando os dados ao usuário
self.nome = input('Nome: ')
self.idade = input('Idade: ')
self.cpf = input('CPF: ')
self.email = input('Email: ')
self.fone = input('Fone: ')
self.cidade = input('Cidade: ')
self.uf = input('UF: ') or 'SP'
date = datetime.datetime.now().isoformat(" ")
self.criado_em = input('Criado em (%s): ' % date) or date
try:
self.db.cursor.execute("""
INSERT INTO clientes (nome, idade, cpf, email, fone, cidade,
uf, criado_em)
34
VALUES (?,?,?,?,?,?,?,?)
""", (self.nome, self.idade, self.cpf, self.email, self.fone,
self.cidade, self.uf, self.criado_em))
# gravando no bd
self.db.commit_db()
print("Dados inseridos com sucesso.")
except sqlite3.IntegrityError:
print("Aviso: O email deve ser único.")
return False
Note que, em criado_em se você não informar uma data ele insere a data atual. E os
parâmetros informados são passados no final do comando execute().
Veja a interação:
$ python3
>>> from manager_db import *
>>> c = ClientesDb()
>>> c.criar_schema()
>>> c.inserir_com_parametros()
Nome: Regis
Idade: 35
CPF: 11100011100
Email: [email protected]
Fone: (11) 1111-1111
Cidade: São Paulo
UF: SP
Criado em (2014-10-07 01:40:48.836683):
Dados inseridos com sucesso.
35
name = fname + ' ' + lname
email = fname[0].lower() + '.' + lname.lower() + '@email.com'
c = gen_city()
city = c[0]
uf = c[1]
lista.append((name, gen_age(), gen_cpf(),
email, gen_phone(),
city, uf, date))
try:
self.db.cursor.executemany("""
INSERT INTO clientes (nome, idade, cpf, email, fone, cidade,
uf, criado_em)
VALUES (?,?,?,?,?,?,?,?)
""", lista)
self.db.commit_db()
print("Inserindo %s registros na tabela..." % repeat)
print("Registros criados com sucesso.")
except sqlite3.IntegrityError:
print("Aviso: O email deve ser único.")
return False
def ler_todos_clientes(self):
sql = 'SELECT * FROM clientes ORDER BY nome'
r = self.db.cursor.execute(sql)
return r.fetchall()
def imprimir_todos_clientes(self):
lista = self.ler_todos_clientes()
print('{:>3s} {:20s} {:<5s} {:15s} {:21s} {:14s} {:15s} {:s}
{:s}'.format(
'id', 'nome', 'idade', 'cpf', 'email', 'fone', 'cidade', 'uf',
'criado_em'))
for c in lista:
print('{:3d} {:23s} {:2d} {:s} {:>25s} {:s} {:15s} {:s}
{:s}'.format(
c[0], c[1], c[2],
c[3], c[4], c[5],
c[6], c[7], c[8]))
def imprimir_todos_clientes(self):
lista = self.ler_todos_clientes()
for c in lista:
print(c)
Mais SELECT
36
Exemplo: Vamos explorar um pouco mais o SELECT. Veja a seguir como localizar um
cliente pelo id. Uma sutileza é a vírgula logo depois do id, isto é necessário porque
quando usamos a ? é esperado que os parâmetros sejam uma tupla.
def contar_cliente(self):
r = self.db.cursor.execute(
'SELECT COUNT(*) FROM clientes')
print("Total de clientes:", r.fetchone()[0])
c.contar_cliente_por_idade(18)
SELECT personalizado
37
Exemplo: Vejamos agora como fazer nosso próprio SELECT.
Para que todas as instruções sejam lidas e retorne valores é necessário que usemos os
comandos split(';') para informar ao interpretador qual é o final de cada linha. E o
comando execute() dentro de um for, assim ele lê e executa todas as instruções SQL
do arquivo.
Novamente você pode usar qualquer instrução SQL porque o commit_db() já está ai.
c.ler_arquivo('sql/clientes_maior60.sql')
38
c = self.localizar_cliente(id)
if c:
# solicitando os dados ao usuário
# se for no python2.x digite entre aspas simples
self.novo_fone = input('Fone: ')
self.db.cursor.execute("""
UPDATE clientes
SET fone = ?
WHERE id = ?
""", (self.novo_fone, id,))
# gravando no bd
self.db.commit_db()
print("Dados atualizados com sucesso.")
else:
print('Não existe cliente com o id informado.')
except e:
raise e
Chamando a função:
c.atualizar(10)
Chamando a função:
c.deletar(10)
def alterar_tabela(self):
try:
self.db.cursor.execute("""
ALTER TABLE clientes
ADD COLUMN bloqueado BOOLEAN;
""")
39
# gravando no bd
self.db.commit_db()
print("Novo campo adicionado com sucesso.")
except sqlite3.OperationalError:
print("Aviso: O campo 'bloqueado' já existe.")
return False
def table_info(self):
t = self.db.cursor.execute(
'PRAGMA table_info({})'.format(self.tb_name))
colunas = [tupla[1] for tupla in t.fetchall()]
print('Colunas:', colunas)
>>> c.table_info()
Colunas: ['id', 'nome', 'idade', 'cpf', 'email', 'fone', 'cidade',
'uf', 'criado_em']
Listando as tabelas do bd
def table_list(self):
l = self.db.cursor.execute("""
SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
""")
print('Tabelas:')
for tabela in l.fetchall():
print("%s" % (tabela))
>>> c.table_list()
Tabelas:
clientes
sqlite_sequence
def table_schema(self):
s = self.db.cursor.execute("""
SELECT sql FROM sqlite_master WHERE type='table' AND name=?
""", (self.tb_name,))
print('Schema:')
for schema in s.fetchall():
print("%s" % (schema))
>>> c.table_schema()
Schema:
CREATE TABLE clientes (
40
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome TEXT NOT NULL,
idade INTEGER,
cpf VARCHAR(11) NOT NULL,
email TEXT NOT NULL UNIQUE,
fone TEXT,
cidade TEXT,
uf VARCHAR(2) NOT NULL,
criado_em DATETIME NOT NULL
)
c.backup('sql/clientes_backup.sql')
Fechando conexão:
def fechar_conexao(self):
self.db.close_db()
41
Conectando-se a outro banco
Agora, no mesmo arquivo manager_db.py vamos criar uma outra instância chamada
PessoasDb(). Neste exemplo vamos relacionar duas tabelas: pessoas e cidades.
Agora os códigos:
class PessoasDb(object):
tb_name = 'pessoas'
def __init__(self):
self.db = Connect('pessoas.db')
self.tb_name
try:
with open(schema_name, 'rt') as f:
schema = f.read()
self.db.cursor.executescript(schema)
except sqlite3.Error:
print("Aviso: A tabela %s já existe." % self.tb_name)
return False
42
c = csv.reader(
open(file_name, 'rt'), delimiter=',')
t = (c,)
for t in c:
self.db.cursor.execute("""
INSERT INTO cidades (cidade, uf)
VALUES (?,?)
""", t)
# gravando no bd
self.db.commit_db()
print("Dados importados do csv com sucesso.")
except sqlite3.IntegrityError:
print("Aviso: A cidade deve ser única.")
return False
def gen_cidade(self):
''' conta quantas cidades estão cadastradas e escolhe uma delas
pelo id. '''
sql = 'SELECT COUNT(*) FROM cidades'
q = self.db.cursor.execute(sql)
return q.fetchone()[0]
para a partir dai gerar valores randômicos apenas com as cidades existentes.
Agora é só alegria!
def ler_todas_pessoas(self):
sql = 'SELECT * FROM pessoas INNER JOIN cidades ON
pessoas.cidade_id = cidades.id'
r = self.db.cursor.execute(sql)
return r.fetchall()
def imprimir_todas_pessoas(self):
lista = self.ler_todas_pessoas()
for c in lista:
print(c)
43
# myselect, imprime todos os nomes que começam com R
def meu_select(self, sql="SELECT * FROM pessoas WHERE nome LIKE 'R%'
ORDER BY nome;"):
r = self.db.cursor.execute(sql)
self.db.commit_db()
print('Nomes que começam com R:')
for c in r.fetchall():
print(c)
def table_list(self):
# listando as tabelas do bd
l = self.db.cursor.execute("""
SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
""")
print('Tabelas:')
for tabela in l.fetchall():
print("%s" % (tabela))
def fechar_conexao(self):
self.db.close_db()
44