associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

PythonComADO

Python com ADO

No ambiente Windows o acesso a banco de dados torna-se bem simples com a utilização do ADO (Active Data Objects), sigla bem comum para os programadores VB e ASP. Aliás, programadores VB conseguirão traçar alguns paralelos em relação a utilização do ADO entre as linguagens (VB e Python) neste tutorial. O ADO pode ser utilizado por qualquer linguagem que dê suporte a tecnologia COM (Common Object Model), como C++, xHarbour, VB, Delphi, e é claro, Python! Sim, se você não sabia, Python tem suporte à COM através da utilização do módulo win32com disponível no pacote win32all (Win32 Extensions do Mark Hammond). Portanto, um dos requisitos para seguir os exemplos deste tutorial é que você possua o pacote win32all instalado, tanto baixando o mesmo da página do criador Mark Hammond ou instalando uma distribuição do Python que já venha com o pacote (como o ActivePython). Além disso, você também deve ter o ADO instalado (a última versão é a 2.7, atualmente, e pode ser baixado no site da Microsoft ou http://www.graymalkin.globalhosts.com.br/files/mdac_typ.zip) além do driver JET 4.0 (também no site da Microsoft ou http://www.graymalkin.globalhosts.com.br/files/jetsetup.zip). É bom lembrar que neste tutorial estarei usando um banco de dados Access como exemplo (aqui não ensino como criá-lo, você deverá usar um já existente), porém o ADO permite se conectar a outros bancos como MySQL, SQL Server, Firebird, etc., desde que seja utilizado o provedor correspondente. Bem, agora, com tudo instalado, mãos à obra. Última nota: estarei comentando não só a utilização do ADO no Python, bem como aspectos da própria linguagem, para que o leitor (que pode ser um programador iniciante, assim como eu) não fique "no espaço" do porquê que tal coisa foi escrita de tal modo.

Em primeiro lugar você deve criar os objetos do ADO, fazendo o seguinte:

   1 import win32com.client #importa o módulo para criar os objetos
   2 
   3 cn = win32com.client.Dispatch("ADODB.Connection")
   4 rs = win32com.client.Dispatch("ADODB.Recordset")

O objeto 'cn' será usado para manipular a conexão com o banco de dados (no nosso caso, com o arquivo físico) e o 'rs' será usado para manipular uma tabela do banco de dados. Necessariamente, você só precisa criar um Connection e quantos Recordsets forem necessários. Vejamos agora como abrir a conexão:

   1 cn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\diretorio\\arquivo.mdb")

Lembre-se que o Python é sensível ao caso, portanto você deve escrever "Open" e não "open". E o quê quer dizer a string passada? Essa string, chamada string de conexão, é que define qual provedor de acesso [Provider] será utilizado e qual o banco de dados [Data Source] (no nosso caso é um arquivo físico, mas em BDs do tipo cliente-servidor será só o nome do banco). E qual o motivo das "\\" ao invés de "\"? Isso se deve ao fato de que a "\" tem um significado especial no Python. A junção da "\" com determinadas letras forma caracteres especiais como o Enter (representado por "\n"). Então para que a "\" apareça realmente é necessário que ela seja dobrada. Faça o teste no interpretador do Python digitando print '\n' e print '\\', e você verá o resultado.

A minha sugestão nesse caso seria usar uma raw string. Ao invés de "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\diretorio\\arquivo.mdb" usar r"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\diretorio\arquivo.mdb", dessa forma erros com relação ao número de "\" seriam evitados (usar o modulo os nesse caso acho que não faz sentido mesmo). - RafaelAlmeida (aFlag)

Abrindo a tabela agora:

   1 sql = "SELECT * FROM tabela"
   2 rs.Open(sql, cn, 2, 3)

Primeiro, definimos sql como uma string com um comando na linguagem SQL (no nosso caso, não precisa-se necessariamente utilizar uma sintaxe SQL, bastava colocar o nome da tabela, todavia é mais interessante utilizar SQL). Como segundo argumento passamos a conexão ativa que é 'cn'. Mas, e esse 2 e 3, o quê significam? O primeiro (2) significa como a tabela deve ser aberta (para escrita e leitura, somente para leitura, etc). Você pode também utilizar variáveis-objetos no lugar, definindo-os:

   1 adOpenDynamic = 2 #leitura e escrita (permite ver alterações ou exclusões feitas por outros usuários)
   2 adOpenForwardOnly = 0 #permite somente que você avance aos registros posteriores, perdendo-se os anteriores
   3 adOpenKeyset = 1 #leitura e escrita (não permite ver alterações ou exclusões feitas por outros usuários)
   4 adOpenStatic = 3 #permite somente leitura

O segundo valor (3) representa como a tabela ou o registro devem ser trancadas (locked). Ele pode assumir os seguintes valores:

   1 adLockBatchOptimistic = 4
   2 adLockOptimistic = 3
   3 adLockPessimistic = 2
   4 adLockReadOnly = 1

Descobrindo os campos existentes na tabela aberta:

   1 for f in rs.Fields:
   2     print f.Name

Apesar de rs.Fields não ser exibido como uma lista (se você tentar print rs.Fields o resultado será <COMObject <unknown>>) ele pode ser usado em uma iteração com o for. Daí, a cada iteração escrevemos a propriedade Name de "f", que representa o nome do campo. Outra propriedade existente é a propriedade Type que representa o tipo de dados contido no campo.

Exibindo registros da tabela aberta:

   1 print rs.Fields['campo1'].value
   2 print rs.Fields['campo2']
   3 print rs.Fields('campo3')

Para exibir o conteúdo dos campos as três formas acima são válidas. A primeira explicita que você quer a propriedade "value" do campo, a segunda utiliza a propriedade padrão (que é a "value") e a terceira utiliza Fields() como uma função cujo paramêtro é o nome do campo.

Adicionando registros na tabela aberta:

   1 rs.AddNew() #inicia a inclusão do registro
   2 rs.Fields['campo1'].value = "valor1" #coloca um valor no campo 'campo1'
   3 rs.Fields['campo2'].value = 5 #coloca um valor no campo 'campo2'
   4 rs.Fields['campo3'].value = "valor3" # coloca um valor no campo 'campo3'
   5 rs.Update() #finaliza a inclusão do registro

Note que para leitura do valor de um campo você pode fazer print rs.Fields("codigo") (utilizando "()") ou print rs.Fields["codigo"], no entando para gravação você deve utilizar "[]", como no exemplo acima. O motivo é óbvio, já que os "()" representam a utilização de uma função e você não pode atribuir um valor à chamada de uma função. O melhor mesmo é se acostumar a utilizar apenas "[]", para evitar confusão.

Procurando um registro:

   1 criterio = "valor=5"
   2 rs.Find(criterio)
   3 if rs.Eof:
   4     print "Registro não encontrado!"
   5 else
   6     print "Registro encontrado!"

Outro exemplo:

   1 criterio = "nome='Junior'"
   2 rs.Find(criterio)
   3 if rs.Eof:
   4     print "Registro não encontrado!"
   5 else
   6     print "Registro encontrado!"

O primeiro exemplo procura um registro cujo campo "valor" seja igual a 5 e o segundo exemplo procura um registro cujo campo "nome" seja igual a string "Junior". Necessariamente, o método Find() só precisa do primeiro paramêtro que é uma string contendo a condição (critério) que deve ser atendido para que um registro seja encontrado. A seguir, verificamos se a propriedade Eof (End of file) do registro é verdadeira (1) ou falsa (0). Isso se deve ao fato de que se o registro não for encontrado, o ponteiro do banco de dados ficará posicionado no final do arquivo, e quando isso ocorre Eof se torna 1. A partir disso, conclui-se se o registro foi ou não encontrado.

Apagando um registro:

   1 rs.Delete()

Sim, é simples assim, lembrando que você deve estar posicionado no registro que você quer apagar. Para o posicionamento (movimentação) você pode utilizar o método Find() para encontrar o registro, ficando automaticamente posicionado nele. Ou utilizar um dos seguintes métodos:

   1 rs.MoveFirst() #vai para o primeiro registro
   2 rs.MoveLast() #vai para último registro
   3 rs.MoveNext() #vai para o próximo registro
   4 rs.MovePrevious() #vai para o registro anterior

Um exemplo de movimentação:

   1 rs.MoveFirst() #vai para o primeiro registro
   2 while not rs.Eof: #enquanto não for o final do arquivo
   3     print rs.Fields['campo1'].value #escreve o conteúdo de "campo1" do registro
   4     rs.MoveNext() #vai para o próximo registro

Nesse exemplo, ele vai para o primeiro registro e em seguida vai mostrando o conteúdo do campo "campo1" até que chegue ao final da tabela (após o último registro, ou seja, EOF).

Fechando uma tabela e a conexão:

   1 rs.Close()
   2 cn.Close()

Simplesmente fecha a tabela e a conexão, sendo bom fazê-lo a fim de garantir que os dados sejam gravados no disco.

O ADO não se limita as propriedades e métodos citados neste tutorial, existindo vários outros de grande importância mas que não citei (como Bof, CancelUpdate(), RecordCount, Filter, Requery(), State, CursorLocation, etc.).

Bem, finda aqui o nosso pequeno tutorial que visa demonstrar o básico para a utilização do ADO no Python, além de exaltar a versatilidade da linguagem Python. Mostra também como programadores VB (como eu!) podem facilmente aprender Python e usufruir de conhecimentos já adquiridos. Para aqueles que já usam ADO no VB, basta apenas adaptar a sintaxe. E para aqueles que queriam um método fácil de acessar bancos de dados no Windows fica aí a dica. Qualquer dúvida, correção, crítica ou sugestão são mui bem aceitos por parte do autor, que pode ser contactado através do email: washingtonj arroba openlink pontocom ponto br

Parabéns! Muito bom esse artigo. -- OsvaldoSantanaNeto

Ao invés de declarar as constantes manualmente, é possível usar o makepy. A maneira mais fácil de fazer isso é rodando o Pythonwin e selecionando Tools/COM Makepy Utility e, na lista que vai aparecer, "Microsoft ActiveX Data Objects 2.7 Library". As constantes e todos os métodos exportados pelos objetos dessa biblioteca passarão a estar disponíveis em tempo de desenvolvimento. Daí basta usar algo como:

   1 from win32com.client import constants as c
   2 ...
   3 rs.Open(sql, cn, c.adOpenDynamic, c.adLockOptimistic)

Como os métodos também estarão disponíveis, o próprio Python checará uma série de erros, e se você estiver usando um ambiente como o Pythonwin, recursos como a auto-compleção funcionarão para os objetos ADO. -- Guilherme Manika


Washington Coutinho Corrêa Junior