0% acharam este documento útil (0 voto)
8 visualizações

Python Dig I Cad

Direitos autorais
© © All Rights Reserved
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
8 visualizações

Python Dig I Cad

Direitos autorais
© © All Rights Reserved
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 297

Curso

DEV
Curso básico de:

Python para
iniciantes.
Sumário
1 - Introdução a Linguagem Python
2 - Variáveis, Tomada de Decisões
3 - Laços de Repetição
4 - Manipulação de Listas e Funções
5 - Arquivos JSON
6 - Dicionário de Dados e Tuplas
7 - Bibliotecas Externas
8 - Protocolos de Comunicação
9 - IoT
Responda:

Por que
Python?
Por que Python?
Python foi lançado em 1991 é a
linguagem de programação mais
utilizada no mundo de segurança da
informação.

O Python é uma linguagem livre, que


depende bastante da sua
comunidade, por isso, não deixe de
participar “ativamente” da
comunidade. Temos uma comunidade
para brasileiros, disponível no site:
http://python.org.br/.
Trabalharemos utilizando a versão 3.6.1, cuidado… pois existem grandes
diferenças entre as gerações 2 e 3 do Python, ou seja, entre o Python 2.x
e o Python 3.x, há um abismo de diferenças que podem interferir
diretamente no seu código.

• Alocação de memória e gerenciamento de recursos são conceitos com


que não precisamos nos preocupar em Python, uma vez que a própria
linguagem se encarrega de controlar, de maneira eficiente, esses serviços.
Em relação ao desenvolvedor, isso é de grande valia, uma vez que o
programador foca apenas no desenvolvimento da sua solução/ferramenta.
Arquitetura Python
O Python trabalha dentro da arquitetura interpretada, ou até mesmo com as duas
arquiteturas (compilada e interpretada) juntas, formando uma arquitetura híbrida.

Quando você gera o seu código-fonte em Python (arquivo com extensão .py),
você pode compilá-lo, o que irá gerar um arquivo com extensão .pyc (Python
Compile), que não é independente, e precisará da ferramenta que irá interpretar o
seu conteúdo, a qual chamamos de PVM (Python Virtual Machine). Logo, para
executar um arquivo compilado em Python, você não precisa do Python como
ferramenta, necessitará apenas da PVM instalada, ou seja, nesse processo ele
compilou e interpretou, logo é híbrido.

Mas como já afirmamos anteriormente, o Python não obriga a compilação, ou


seja, um arquivo .py (código fonte) pode ser diretamente interpretado pela PVM
(essa é a situação mais comum de utilização do Python no mercado), logo ele é
interpretado.
Python é alto nível
Imagine uma longa estrada, onde, em uma das suas extremidades, encontraremos a CPU e,
na outra, o desenvolvedor. Pois bem, quando você trabalha com linguagem de alto nível, o
seu código parte de um ponto dessa estrada, mais próximo ao desenvolvedor. Isso significa
que ele está mais distante da CPU e, para chegar lá, vai demorar um pouco mais, quando
comparamos com uma linguagem de baixo nível, que está mais próxima da CPU.

A quantidade de processos que existem entre a ferramenta do desenvolvedor e a CPU será


maior quando a linguagem utilizada é de alto nível, e haverá menos processos quando a
linguagem for de baixo nível. Por outro lado, pelo fato de a linguagem de alto nível estar
mais próxima do desenvolvedor, é mais legível para ele. Por exemplo, observe as linhas
abaixo:
se nota<6 .e. nota>=4 então (VisualG)
if nota<6 and nota>=4: (Python)
if (nota<6 && nota>=4) { (Java)
Instalando Python
Download Python:
https://www.python.org/downloads/release/python-361/

Durante a instalação selecione a opção "Add Python 3.6 to PATH"


No prompt de comando, digite Python e, então, estará dentro do IDLE, que é o ambiente
puro do Python para o desenvolvimento. Ou seja, você já está dentro do Python para
programar.
• Digite exit() e pressione <enter> para sair do IDLE.
• Digite exit e pressione <enter> para sair do CMD.

Download PyCharm
PyCharm, é um dos IDE's mais utilizadas para programação Python. Um IDE permite
programar em determinada linguagem e possui recursos que viabilizam a produtividade
e a praticidade durante o desenvolvimento e a execução do seu programa.
https://www.jetbrains.com/pycharm/download/
Vamos começar com Hello World ??

Abra o PyCharm e siga os passos abaixo:


Clique em novo projeto;
Defina o Local em que o projeto será salvo;
Crie um diretório abaixo do projeto;
Adicione um arquivo python dentro do diretório com nome HelloWorld.py;
Digite o código abaixo:

print("Hello World")
ou
mensagem = "Hello World"
print(mensagem)

Reutilização, legibilidade e organização, são os benefícios de se armazenar valores


em uma variável
Variavéis, Tomada de decisão e Estruturas de repetição

O que são variáveis?


Variáveis são espaços reservados na memória do computador para que possamos
armazenar, temporariamente, um determinado dado.
Vale ressaltar que “dado” é algo que por si só e de maneira isolada não possui
significado para o usuário final. O “dado” apenas passa a ter significado para o usuário
final quando o combinamos com outros “dados”, tornando-o uma “informação”.

Se eu falar para você: dezenove. O que significa? Você pode pensar: é uma
dezena ou é uma idade, é a temperatura ambiente ou é a quantidade de alunos, é a
quantidade de tarefas ou é a quantidade de pontos que uma equipe de basquete
realizou, enfim, o dado “dezenove” por si só não tem significado, pois pode ser qualquer
uma dessas hipóteses ou até mesmo todas as hipóteses.
Variavéis, Tomada de decisão e Estruturas de repetição

Agora, se eu falar: dezenove sobrinhos, você saberá que estou falando em


quantidade de pessoas, mas ainda não tem a informação exata, por quê? Porque
faltam dados. Quanto mais dados tivermos, melhor poderá ser a informação que
obteremos. Podemos chegar a uma informação do tipo: tenho dezenove
sobrinhos, dez com mais de 20 anos e os outros nove com menos ou exatamente
20 anos.

Regras: os três itens abaixo são obrigatórios e, caso não sejam seguidos,
tornarão o seu código inoperante e a sua aplicação não irá funcionar.
• O nome da variável não pode iniciar com um número. Exemplo: 1berto não
pode ser um identificador de variável.

• O identificador não pode fazer uso de palavras reservadas da linguagem.


Variavéis, Tomada de decisão e Estruturas de repetição

As palavras reservadas são comandos/indicações que pertencem à


linguagem. Por isso, não podem ser utilizadas como nomes de variáveis.
Por exemplo: if, while, for, entre tantas outras, são palavras reservadas da
linguagem Python, não podem ser utilizadas como identificadores.

• Cuidado na utilização de caracteres especiais como: @ # ! ? ( ) [ ] { },


entre tantos outros que não podem ser utilizados em nomes de variáveis,
porque também fazem parte da linguagem de programação. O único
caractere especial que pode ser utilizado para o identificador de uma
variável é o underline _.
Variavéis, Tomada de decisão e Estruturas de repetição

Padrões: não são obrigatórios, mas são importantíssimos para que possamos
manter um código “clean” onde qualquer programador terá facilidade em realizar
a leitura do seu código e eventuais manutenções. Utilizar padrões é fazer uso de
uma boa prática de programação. Vamos aos padrões:

• O identificador de uma variável sempre deverá começar com letra


minúscula (caixa baixa), nunca inicie o nome de uma variável com letra
maiúscula.

• Letras maiúsculas somente devem ser usadas quando você fizer uso de
duas ou mais palavras para compor o identificador de uma variável. A letra
maiúscula identifica o início de uma nova palavra, o que facilita muito para
outras pessoas que não conhecem o idioma do código que estiver sendo
lido/interpretado.
Variavéis, Tomada de decisão e Estruturas de repetição

Exemplos válidos: dataDeNascimento ou dataNascimento ou data_nascimento.


Como você pode perceber, também pode utilizar o underline para separar as
palavras, dispensando o uso dos caracteres maiúsculos no nome das variáveis.

• Utilize nomes significativos, nada de nomes como: xpto, x, y, z, abc, entre


tantos outros bem criativos, porém, sem qualquer significado para outros
profissionais. Lembre-se que você irá precisar do nome da sua variável no
decorrer do código.
• Acrônimos (siglas que resumem palavras a fim de agilizar o processo de
comunicação) devem ser utilizados também com letras minúsculas.
Exemplos: cpf, cep, rg, cnpj

Vamos verificar alguns identificadores válidos:


numeroElemento2 produto_alimenticio endereco
código_do_cliente descricaoCurso qtdeDeItens
Variavéis, Tomada de decisão e Estruturas de repetição

Tipos de dados
Numérico;
Alfanumérico;

Digite o código abaixo em um novo arquivo python chamado variaveis.py:

nome="Ricardo Galacho"
empresa='Digicad'
qtde_funcionarios=100
mediaMensalidade=2000.00

Se você executar o programa, não vai acontecer nada visualmente, pois você
está apenas criando as variáveis e atribuindo dados a elas. Repare no código
alguns
detalhes que podemos destacar:
Variavéis, Tomada de decisão e Estruturas de repetição

Na linha 1 incluímos um comentário para exibir o que está sendo feito no bloco;

Nas linhas 2 e 3, criamos variáveis do tipo String, ou seja, o conteúdo de uma variável
String deve sempre estar entre aspas/aspas duplas (“) ou entre apóstrofos/aspas
simples (‘).
Na linha 4, criamos uma variável do tipo int.

Na linha 5, criamos uma variável do tipo float. O caractere utilizado para casas
decimais é o ponto (.) seguindo o padrão americano, ou seja, vírgula separa casas de
milhar e ponto separa casas decimais.

Para que possamos exibir o conteúdo de cada variável, utilizaremos a função print(), por
isso, devemos acrescentar ao código as seguintes linhas:

print(nome + " trabalha na empresa " + empresa)


print("Possui: ", qtde_funcionarios, " funcionarios.")
print("A média da mensalidade é de: " + str(mediaMensalidade))
Variavéis, Tomada de decisão e Estruturas de repetição
Detalhando:

• Na linha 8, exibimos o valor das duas primeiras variáveis, separadas por um texto;
para unir o conteúdo delas, utilizamos o operador “+”, que representa concatenação/junção
para string´s.

• Na linha 9, onde estamos exibindo a variável inteira e dois textos, utilizamos a “virgula” para
indicar o final do primeiro texto, a variável e o início do segundo texto, sem precisar converter
a variável numérica para string.

• Na linha 10, exibimos um texto e uma variável do tipo “float”, concatenadas através do
operador “+”. Para que o Python não tente realizar uma operação matemática, devemos
utilizar a função str() para converter o conteúdo da variável “float” para string, por isso a
variável mediaMensalidade está dentro da função str().
Variavéis, Tomada de decisão e Estruturas de repetição
Podemos exibir as variáveis numéricas (int ou float), com as string´s, utilizando a forma
definida na linha 8 ou conforme apresentado na linha 9. Execute e verá a saída dos dados das
variáveis transformada em informação para o usuário final. Caso não lembre como executar a
sua aplicação, clique no seu arquivo “Variaveis” com o botão direito e selecione a opção “Run
Variaveis”.

Entretanto, se você executar dez vezes o seu arquivo, verá a mesma mensagem, ou seja, suas
variáveis não estão variando tanto assim, não é mesmo? Por isso, vamos utilizar a função
input(), assim como a função print() exibe. A função input() permitirá que o usuário final
possa digitar um conteúdo em tempo de execução.

Vamos criar agora o arquivo python Variaveis2.py


Variavéis, Tomada de decisão e Estruturas de repetição
nome=input("Digite um funcionário: ")
empresa=input("Digite a instituição: ")
qtde_funcionarios=int(input("Digite a qtde de funcionários: "))
mediaMensalidade=float(input("Digite a média da mensalidade: "))
print(nome + " trabalha na empresa " + empresa)
print("Possui: ", qtde_funcionarios, " funcionarios.")
print("A média da mensalidade é de: " + str(mediaMensalidade))

Execute e veja que as variáveis agora realmente estão funcionando como variáveis, pois, a
cada execução, os valores podem mudar. Atente-se que você deverá digitar os valores na
parte inferior da tela, conforme a imagem abaixo:
Variavéis, Tomada de decisão e Estruturas de repetição

Detalhe para as linhas 3 e 4 agora, onde estamos fazendo conversões de string para int (na
linha 3) e de string para float (na linha 4). Isso porque o input() captura apenas strings, logo
após capturado o valor, convertemos para o tipo de dado que desejamos armazenar em sua
respectiva variável.
Variavéis, Tomada de decisão e Estruturas de repetição
Tomada de decisão
Durante o desenvolvimento de um código, existem diversas situações em que a resolução
dependerá de um valor para que possa seguir um rumo e, consequentemente, que uma
tomada de decisão também seja seguida. Isso ocorre muito em nosso dia a dia quando
planejamos uma tarefa, mas as “variáveis” do nosso cotidiano fazem com que tenhamos que
optar por mudanças de planos.
Para que estas tomadas de decisões sejam possíveis, utilizaremos um comando condicional
muito conhecido em todas as linguagens de programação, identificado como “if”.

A forma de utilizar o comando “if”, ou seja, sua sintaxe, é bem simples:


if <condição>:
• A linha do if deve ser encerrada com dois pontos (:).
• A(s) linha(s) a ser executada(s), caso a condição seja verdadeira, deverá(ão) estar com um
recuo da margem esquerda. Este recuo deve ser realizado através da tecla <TAB>. Tudo que
estiver recuado, abaixo do if, será executado somente se a condição for verdadeira.
Variavéis, Tomada de decisão e Estruturas de repetição
nota = 6
if nota >= 7:
print("Voce está de...")
print("Parabéns!!")
print("Esse texto será exibido se a nota for maior ou igual a 7")
print("Esse texto será exibido independente da condição do if")

Decisões Simples:
Uma decisão simples é o caso mais comum e corriqueiro que existirá dentro de um código.
nome=input("Digite o nome: ")
idade=int(input("Digite a idade: "))
prioridade="NÃO"
if idade>=65:
prioridade="SIM"
print("O paciente " + nome + " possui atendimento prioritário? " + prioridade)
Variavéis, Tomada de decisão e Estruturas de repetição
Decisões Compostas:
nome=input("Digite o nome: ")
idade=int(input("Digite a idade: "))
if idade>=65:
print("O paciente " + nome + " POSSUI atendimento prioritário!")
else:
print("O paciente " + nome + " NÃO possui atendimento prioritário!")

Agora economizamos recursos. Perceba que, no exemplo anterior, (DecisaoSimples),


utilizamos três variáveis e, como já mencionado, variáveis ocupam espaço em memória.
Preste muita atenção nos recuos, perceba que o “else:” está alinhado com o “if” e que cada
comando possui uma linha tabulada. Também poderemos encontrar uma situação em que o
Verdadeiro e o Falso,simplesmente, não sejam suficientes. Por exemplo, vamos imaginar que
pessoascom idade igual ou superior a 65 receberão atendimento prioritário, mas que
também pessoas com suspeita de doenças infecto-contagiosas deverão ser direcionadas
para uma sala de espera distinta, por motivos óbvios.
Variavéis, Tomada de decisão e Estruturas de repetição
nome=input("Digite o nome: ")
idade=int(input("Digite a idade: "))
doenca_infectocontagiosa=input("Suspeita de doença infectocontagiosa?").upper()
if idade>=65:
print("O paciente " + nome + " POSSUI atendimento prioritário!")
elif doenca_infectocontagiosa=="SIM":
print("O paciente " + nome + " deve ser direcionado para sala de espera
reservada.")
else:
print("O paciente " + nome + " NÃO possui atendimento prioritário e
pode aguardar na sala comum!")

Um destaque para o final da terceira linha, na qual utilizamos uma função


chamada “upper()”. Veja que implementamos no código acima um comando chamado “elif:”,
que é uma sigla para “else”+”if”.
Variavéis, Tomada de decisão e Estruturas de repetição
Repare também ainda na linha do “elif:” que utilizamos o operador “==”, o qual
deve ser implementado para indicar comparação, por isso, muito CUIDADO, um “=”
representa atribuição, dois “==” representam comparação

Dessa forma, o “else” somente será executado se a primeira e a segunda


condição forem falsas. Mas e se o paciente tiver idade igual ou maior a 65 anos ??

Vamos utilizar os operadores “AND” ou “OR”, que nos permitem colocar duas
ou mais condições dentro de um único “if” e/ou “elif”. Quando utilizamos o operador
“AND”, queremos dizer que a condição que estiver à esquerda e a condição que
estiver à direita do operador devem ser verdadeiras para que o “if” seja considerado
Verdadeiro. Se uma das condições retornarem Falso, o “if” irá retornar Falso.
Já o operador “OR” determina que se uma das condições for verdadeira, o “if”
já deverá retornar “Verdadeiro”. Para simplificar o que queremos fazer, vamos
imaginar a seguinte situação: o paciente chega à triagem que o direcionará à sala de
espera da consulta.
Variavéis, Tomada de decisão e Estruturas de repetição
nome=input("Digite o nome: ")
idade=int(input("Digite a idade: "))
doenca_infectocontagiosa=input("Suspeita de doença infecto�contagiosa?").upper()
if idade>=65 and doenca_infectocontagiosa=="SIM":
print("O paciente será direcionado para sala AMARELA - COM prioridade")
elif idade < 65 and doenca_infectocontagiosa == "SIM":
print("O paciente será direcionado para sala AMARELA - SEM prioridade")
elif idade >= 65 and doenca_infectocontagiosa == "NAO":
print("O paciente será direcionado para sala BRANCA - COM prioridade")
elif idade < 65 and doenca_infectocontagiosa == "NAO":
print("O paciente será direcionado para sala BRANCA - SEM prioridade")
else:
print("Responda a suspeita de doença infectocontagiosa com SIM ou NAO")
Variavéis, Tomada de decisão e Estruturas de repetição
Decisões encadeadas

As decisões encadeadas servem para avaliarmos uma situação e,


dependendo da situação, serão tomadas algumas outras decisões. Por isso, servem
como uma alternativa para estruturas mais robustas, como a que foi vista no último
tópico ou ainda para verificar mais possibilidades para um mesmo dado sem a
utilização dos operadores “and” ou “or”.

Podemos pensar em uma string que não tenha apenas os valores “SIM” e
“NAO”, como o estado civil, que pode ter mais do que simplesmente dois valores
(solteiro, casado, divorciado, viúvo etc.).

Crie um arquivo no diretório “Capitulo2” chamado “DecisaoEncadeada.py” e veja como


ficaria o mesmo código do último tópico, mas agora com decisão encadeada
Variavéis, Tomada de decisão e Estruturas de repetição
Decisões encadeadas

nome=input("Digite o nome: ")


idade=int(input("Digite a idade: "))
doenca_infectocontagiosa=input("Suspeita de doença
infectocontagiosa?").upper()
if idade >= 65:
print("Paciente COM prioridade")
if doenca_infectocontagiosa=="SIM":
print("Encaminhe o paciente para sala AMARELA")
elif doenca_infectocontagiosa=="NAO":
print("Encaminhe o paciente para sala BRANCA")
Variavéis, Tomada de decisão e Estruturas de repetição
Decisões encadeadas

O resultado final para o usuário final é o mesmo, a diferença é que iremos


resolvendo o problema por partes. Levando em consideração o código acima,
primeiro vamos identificar a idade do paciente para definir se ele terá atendimento
prioritário ou não, e depois se o paciente está ou não sob a situação suspeita de
doença infecto-contagiosa.

Você deve estar se perguntando: então, tanto faz usar decisão composta ou
decisão encadeada? Para o exemplo acima, poderíamos dizer que sim, mas, na
prática, não é bem assim. Observe que temos apenas duas condições (idade e
suspeita de doença infecto-contagiosa).

Além disso, a decisão encadeada foi desenvolvida para que se possa tomar
uma decisão somente quando outra decisão já foi definida como verdadeira ou falsa.
Variavéis, Tomada de decisão e Estruturas de repetição

Vamos para o seguinte caso: mulheres grávidas também são consideradas


para o atendimento prioritário (sala Branca ou Amarela). Você vai perguntar para
todos os pacientes se eles estão grávidos? Não, apenas para as mulheres

Todas ?

Logo, não seria possível resolver essa situação, de maneira lógica e prática,
utilizando a decisão composta. Vamos criar outro arquivo chamado:
“DecisaoEncadeada2.py” e montaremos o seguinte código:

nome = input("Digite o nome: ")


idade = int(input("Digite a idade: "))
doenca_infectocontagiosa = input("Suspeita de doença infectocontagiosa?").upper()
Variavéis, Tomada de decisão e Estruturas de repetição
# PRIMEIRO PROBLEMA A SER RESOLVIDO
if doenca_infectocontagiosa == "SIM":
print("Encaminhe o paciente para sala AMARELA")
elif doenca_infectocontagiosa == "NAO":
print("Encaminhe o paciente para sala BRANCA")
else:
print("Responda a suspeita de doença infectocontagiosa com SIM ou NAO")
# SEGUNDO PROBLEMA A SER RESOLVIDO
if idade >= 65:
print("Paciente COM prioridade")
else:
genero = input("Digite o gênero do paciente: ").upper()
if genero == "FEMININO" and idade > 10:
gravidez = input("A paciente está grávida? ").upper()
if gravidez == "SIM":
Variavéis, Tomada de decisão e Estruturas de repetição
print("Paciente COM prioridade")
else:
print("Paciente SEM prioridade")
else:
print("Paciente SEM prioridade")

Delimitamos os dois problemas utilizando o caractere “#’. hashtag, sua função é a de


indicar que a linha iniciada com este caractere não deve ser compilada, ou seja, não é uma
linha de comandos e, sim, uma linha particular de comentários do programador.

Este código é um pouco maior e possui algumas tomadas de decisão, percebe-se nesse
caso que a identação do código é extremamente importante no Python!
Variavéis, Tomada de decisão e Estruturas de repetição
Laços de repetições:

Imagine, sobre o nosso último código digitado, a seguinte situação:


deveremos inserir os dados de 10 pacientes no sistema. Para você realizar este
cadastro, deveria executar o mesmo programa 10 vezes. Imagine, então, agora,
cadastrar 100 pacientes, 1.000 pacientes, o nosso código está pouco produtivo,
concorda? É aí que entram as repetições.
Os laços de repetições servem para que uma determinada ação
(representada por um conjunto de códigos) seja repetida uma determinada ou
indeterminada quantidade de vezes. Esse recurso é muito importante dentro da
programação, pois permite uma redução drástica em relação à quantidade de linhas
digitadas.
Basicamente, no Python, encontramos dois comandos que podem ser
utilizados para realizar repetições de trechos de códigos, são eles: while e for.
Veremos, a seguir, as diferenças entre eles.
Variavéis, Tomada de decisão e Estruturas de repetição
Laços de repetições:

Estrutura While é a mais utilizada, funciona como um if mas a diferença é que executa o
bloco enquanto uma condição for verdadeira e não somenta uma vez:

• Testa a condição – se verdadeira.


• Executa o bloco de código.
• Volta para condição.

numero = int(input("Digite um numero: "))


while numero < 100:
print("\t" + str(numero))
numero = numero + 1
print("Laço encerrado....")
Variavéis, Tomada de decisão e Estruturas de repetição
Repare que se a condição for eternamente verdadeira, você criará o que chamamos de “loop
infinito”, isto é, o programa ficará executando este bloco de código até que o programa seja
encerrado de maneira abrupta, seja por falha do sistema, estouro da memória, computador
foi desligado ou algo do gênero.

Conseguiu verificar que a forma de usar (sintaxe) o “while” é idêntica à do comando “if”?
• Dentro da string que está dentro do print(), utilizamos o caractere “\t”
(lemos: contra barra t), cuja função é acrescentar uma tabulação antes do número, um
detalhe apenas para que o número não saia impresso colado na margem esquerda do
console.

Na linha 4, é o que garantimos que o nosso “while” seja finito, pois a condição é continuar
desde que o valor da variável “numero” seja menor que 100.
Variavéis, Tomada de decisão e Estruturas de repetição
Caso o valor digitado pelo usuário final seja um valor maior ou igual a 100,
nada que está dentro do laço será executado, o programa vai pular para a
linha 5, que está fora do laço, de acordo com a tabulação.

Você pode alterar na linha o valor “1” por outro número qualquer, a fim de
verificar que o valor da variável “numero” irá saltar de acordo com a
alteração que fizer nesta operação de soma (atribuição).

Experimente comentar a linha 4 (coloque o # no início da linha), você verá


que cairá em um “loop infinito”, pois o valor da variável não será alterado
em momento algum, ou seja, a condição será eternamente verdadeira.

CLICA NO STOOOPPP
Variavéis, Tomada de decisão e Estruturas de repetição

A estrutura “for” também permite uma repetição, mas sua aplicação é um


tanto quanto diferente quando comparada ao “while”. O “for” indica o término do laço
de duas formas básicas: por um número que delimita o seu final ou por uma lista de
dados que foi verificada por completo.

Crie um arquivo chamado “For.py” dentro da pasta “Capitulo2” e monte o seguinte código:
for numero in range(1, int(input("Digite um numero para determinar o fim: ")), 1):
print("\t" + str(numero))

Para o comando “for”, perceba que criamos uma variável chamada “numero”
e dizemos que, de acordo com a função “range()” (que permite especificar uma faixa
de valores e como será incrementada), a variável iniciará com o valor 1 até o valor
que for digitado pelo usuário final. E esta faixa será incrementada de 1 em 1,
conforme o último valor especificado dentro da função range().
Variavéis, Tomada de decisão e Estruturas de repetição

Como já podemos perceber, esta forma de laço não é a mais adequada para
os momentos de preenchimento de dados de um projeto. Não temos como afirmar
quantos usuários serão cadastrados, ou quantos pacientes serão atendidos, este é
um caso típico para o “while”. Por outro lado, quando os dados já existem e
precisamos simplesmente exibi-los ou até mesmo realizar uma pesquisa dentro
deles, o “for” fica como o comando mais utilizado para percorrer todos os elementos
de um determinado conjunto

Usando o “for”, tente montar um código que exiba a tabuada de um valor que
será digitado pelo usuário final. Para isso, crie um arquivo chamado
“tabuada_for.py”. Não olhe o código a seguir, tente fazer primeiro, ok?
Variavéis, Tomada de decisão e Estruturas de repetição

tabuada=int(input("Digite um número para exibir a tabuada: "))


print("Tabuada do número ", tabuada)
for valor in range(1,11,1):
print(str(tabuada) + " x " + str(valor) + " = " + str((tabuada*valor)))

Repare que, para multiplicarmos os dois valores, utilizamos o operador “*”. No


range(), definimos que os valores gerados deverão estar entre 1 e 11, com
incremento de 1 em 1. O “11” foi definido porque ele não se inclui no range, ou seja,
quando chegar em 11 ele para, portanto, não executará mais o laço quando atingir
este valor.

Preparamos muitos códigos, mas muita coisa ainda vem pela frente. Procure
refazer, principalmente, os desafios deste capítulo, antes de entrar no próximo,
quando, então, explicaremos sobre listas, uma das principais estruturas de
armazenamento temporário do Python.
Listas e Funções

Neste capítulo, abordaremos dois assuntos que são importantíssimos para o


desenvolvimento Python, são eles: as listas e as funções. Você verá como as listas
maximizam a captura dos dados e permitem, com as variáveis e os laços, o
desenvolvimento de uma aplicação que atenda às reais necessidades de qualquer
usuário final, tornando o seu código dinâmico.
Já as funções serão as responsáveis por nos acompanhar durante todo o
restante do curso, já utilizamos algumas funções próprias do Python, como: input() e
print(), por exemplo. Entretanto, as funções possuem muito mais poderes. Podemos
utilizar funções de outros programadores, importando-as dentro dos nossos projetos
e criar as nossas próprias funções (assunto que será abordado neste capítulo) para
que outros programadores possam utilizá-las.
Listas e Funções

Variável, precisa de uma ajuda?

Todas as linguagens possuem formas particulares para armazenamento de dados


voláteis ( dados em memória enquanto o sistema está aberto ) No Python, utilizamos as
variáveis par a armazenar esses dados. Entretanto, passaremos por situações em que a
variável não será o recurso mais indicado, pensando em desenvolver um código limpo e
reduzido, por exemplo, iremos pesquisar em um conjunto de dados (banco de dados)
todos os usuários que possuem acesso ao sistema para a realização de uma
auditoria. Cada usuário seria identificado por uma variável, certo? Mas quantos
usuários serão pesquisados? Precisaremos de quantas variáveis? Percebe que é
impossível definirmos um valor exato?
Listas e Funções

A solução, então, seria criarmos mil variáveis, pensando que o número mil jamais seria
alcançado? Não, em vez disso, iremos criar uma única e singela lista que pode armazenar
quantos usuários desejarmos.
Se ainda não ficou claro, vamos pensar em mais um exemplo: todas as máquinas da nossa
clínica possuirão um gerador de “log”, que nada mais é do que um arquivo do tipo texto
com informações capturadas em relação às ações do dia a dia. Podemos inserir no arquivo
de log informações sobre qual usuário acessou aquele computador e em qual horário
esteve ativo. Mais uma vez, não temos um valor exato. Qual a solução? Isso...utilizaremos
listas!!!
Então, podemos concluir que as listas armazenam uma quantidade
indeterminada de dados? Não é bem assim, pois existe o limite físico da memória do
seu computador, mas esse limite é tão grande que jamais chegaremos a alcançá-lo
dentro de uma situação profissional em que você faça uso das boas práticas e não
tenha intenções reais em “estourar a memória” do computador.
Listas e Funções

Poderíamos fazer a seguinte analogia: a variável seria o corpo humano, e em


cada corpo só é possível “armazenar” um único indivíduo. Já a lista seria como o
planeta Terra, onde podemos armazenar vários indivíduos, um número finito é
verdade, mas uma quantidade indeterminada e longe da capacidade máxima de
armazenamento.

As listas, assim como as variáveis, devem seguir as regras e a padronização


em relação aos seus identificadores (nomes), ou seja, nada de usar os seguintes
nomes para as listas: while, for, n@me, 1berto, entre outros identificadores inválidos.
Todas as listas podem ser inicializadas vazias ou com dados; caso você opte
por criar uma lista vazia, deverá igualá-la, conforme é demonstrado no código
abaixo.
Listas e Funções

#lista preenchida estaticamente


lista_estatica = ["xpto", True]
#lista preenchida dinamicamente
lista_dinamica = [input("Digite o usuário: "), bool(int(input("Está logado? ")))]
#lista vazia
lista_vazia=[]
Observe que, em todos os casos, os valores de uma lista devem estar entre
colchetes “[ ]”, mesmo quando a lista for declarada vazia.
Na “lista_dinamica”, o segundo item está passando por duas conversões. Isso
ocorreu porque desejamos um dado do tipo “boolean”, ou seja, um dado booleano
que pode possuir apenas os valores “True” ou “False”. Esse tipo de dado é utilizado
normalmente para perguntas que possam ter como resposta somente os valores
“sim” ou “não”, como é o caso do nosso exemplo, a pergunta “Está logado?”
somente pode ter as respostas “sim” ou ”não”.
Listas e Funções

Como o input retorna uma string, devemos converter o dado para int (inteiro),
para, então, posteriormente, convertê-lo para bool (booleano). Não podemos fazer a
conversão diretamente de string para bool. O valor retornado será “False” somente
se o número informado for igual a zero, qualquer outro valor trará o retorno “True”.
Vamos adicionar dados agora ?

inventario=[]
resposta="S"
while resposta=="S":
inventario.append(input("Equipamento: "))
inventario.append(float(input("Valor: ")))
inventario.append(int(input("Número Serial: ")))
inventario.append(input("Departamento: "))
resposta=input("Digite \"S\" para continuar: ").upper()
Listas e Funções

Agora, vamos acrescentar as estruturas de repetição que conhecemos para preencher e


exibir os dados de uma lista ? Copie o código abaixo:

inventario=[]
resposta="S"
while resposta=="S":
inventario.append(input("Equipamento: "))
inventario.append(float(input("Valor: ")))
inventario.append(int(input("Número Serial: ")))
inventario.append(input("Departamento: "))
resposta=input("Digite \"S\" para continuar: ").upper()
for elemento in inventario:
print(elemento)
Listas e Funções

No código acima, utilizamos o nosso conhecido comando “while”, que será


responsável por seguir adicionando dados para a nossa lista “inventario” enquanto o
usuário digitar “S”.
Perceba no código acima que utilizamos o método append() para adicionar
novos itens em nossa lista. Podemos afirmar que a cada passagem dentro do
“while”, quatro novos dados serão adicionados na lista (nome do equipamento, valor
do equipamento, número serial do equipamento e o nome do departamento onde se
encontra o equipamento).
Listas e Funções

A estrutura foreach nos permite definir um nome para cada elemento que ele
encontrar na lista. No nosso caso, chamamos de “elemento” e, então, ele irá
percorrer todas as posições da lista e exibir todos os valores. Poderíamos também,
em vez de criar uma única lista, criar uma lista para cada dado, por exemplo, uma
lista para equipamento, outra para valor, número serial e departamento,
respectivamente. Vamos tentar? Crie um novo arquivo chamado: “MultiplasListas.py”
e tente montar o código sozinho, antes de continuar a leitura.

equipamentos = []
valores = []
seriais = []
departamentos = []
resposta = "S"
while resposta == "S":
Listas e Funções

equipamentos.append(input("Equipamento: "))
valores.append(float(input("Valor: ")))
seriais.append(int(input("Número Serial: ")))
departamentos.append(input("Departamento: "))
resposta = input("Digite \"S\" para continuar: ").upper()
for equipamento in equipamentos:
print("Equipamento: ", equipamento)

Repare agora que estamos utilizando quatro listas, mas que o nosso “for”
somente mostra os nomes dos equipamentos, que é o conteúdo da lista
“equipamentos”. E para saber os outros dados? Precisaríamos criar mais três laços
com o “for”? A resposta é...não. Podemos utilizar os índices, como veremos no
próximo tópico.
Listas e Funções

Índice

O índice é o número que define onde está armazenado um elemento dentro


de uma lista. Quando um primeiro append() é executado na lista, ele abre a posição
0 (zero) para armazenar o dado, quando ele for executado novamente, abrirá a
posição 1 (um) para o próximo dado, e assim sucessivamente.

Vamos alterar o código do nosso “for”, da seguinte forma:

equipamentos = []
valores = []
seriais = []
departamentos = []
resposta = "S"
Listas e Funções

Índice

while resposta == "S":


equipamentos.append(input("Equipamento: "))
valores.append(float(input("Valor: ")))
seriais.append(int(input("Número Serial: ")))
departamentos.append(input("Departamento: "))
resposta = input("Digite \"S\" para continuar: ").upper()
for indice in range(0,len(equipamentos)):
print("\nEquipamento..: ", (indice+1))
print("Nome.........: ", equipamentos[indice])
print("Valor........: ", valores[indice])
print("Serial.......: ", seriais[indice])
print("Departamento.: ", departamentos[indice])
Listas e Funções

Índice
A estrutura do nosso “for” mudou, agora não estamos trabalhando com base
nos elementos diretamente, mas, sim, de acordo com o índice. Para a variável
“índice” que criamos no “for”, será atribuído o valor de 0 até a quantidade de
elementos que existirem dentro da nossa lista “equipamentos” (função “len()”), que
obviamente será a mesma quantidade de elementos que existirão nas listas: valores,
seriais e departamentos, conforme apresentado nas tabelas do tópico anterior, deste
mesmo capítulo.
Com o índice em mãos, poderemos recuperar os dados de todas as nossas listas e a saída
dos dados ficará muito mais apresentável.
Listas e Funções

Ainda com listas, podemos pesquisar um determinado dado, digite o código


abaixo, no final do nosso arquivo “MultiplasListas2.py”:

busca=input("\nDigite o nome do equipamento que deseja buscar: ")


for indice in range(0,len(equipamentos)):
if busca==equipamentos[indice]:
print("Valor..: ", valores[indice])
print("Serial.:", seriais[indice])

Observamos acima que, dentro do “for”, montamos uma tomada de decisão


simples, cuja função será comparar o conteúdo da variável “busca” com todos os
elementos que estiverem armazenados dentro da lista “equipamentos”. Quando ele
encontrar um valor igual, irá exibir, então, o valor e o número serial desse
equipamento.
Vamos imaginar algumas outras situações:
Listas e Funções

Situação 1: todos os equipamentos “impressora” receberão uma


depreciação (desvalorização após certo período) de 10%. Monte o código
que seria responsável por alterar o valor de todos os equipamentos
“impressora”.

• Situação 2: um equipamento com um determinado número serial foi


danificado e será descartado. Precisamos eliminar esse equipamento.
Dica: para eliminar um item de uma lista, você utilizará o comando “del”.
Exemplo: del lista[<indice>]

Tente elaborar o código das duas situações propostas. Veja a seguir os


códigos que resolveriam essas tarefas.
Listas e Funções

depreciacao=input("\nDigite o nome do equipamento que será depreciado: ")


for indice in range(0,len(equipamentos)):
if depreciacao==equipamentos[indice]:
print("Valor antigo: ", valores[indice])
valores[indice] = valores[indice] * 0.9
print("Novo valor: ", valores[indice])

Como podemos observar no código acima, quando igualamos uma lista


(acompanhada de um índice), sobrescrevemos o conteúdo do dado na posição
especificada pelo índice, ou seja:
departamentos[0]=”Teste” => essa linha seria responsável por substituir pela
string “Teste” o dado que está na posição zero.
Para a solução da segunda situação, o seu código deve ser semelhante a:
Listas e Funções

serial=int(input("\nDigite o serial do equipamento que será excluido: "))


for indice in range(0, len(departamentos)):
if seriais[indice]==serial:
del departamentos[indice]
del equipamentos[indice]
del seriais[indice]
del valores[indice]
break
for indice in range(0,len(equipamentos)):
print("\nEquipamento..: ", (indice+1))
print("Nome.........: ", equipamentos[indice])
print("Valor........: ", valores[indice])
print("Serial.......: ", seriais[indice])
print("Departamento.: ", departamentos[indice])
Listas e Funções

No código acima proposto, repare que utilizamos o comando “break” dentro


do “if”. O que significa que quando ele encontrar o valor desejado irá excluir o
elemento da posição onde foi encontrado e depois irá sair do laço “for” (função do
break).

Isso porque, a partir do momento que excluímos um item, o índice poderá se


perder, pois um elemento foi excluído e, consequentemente, o contador (laço) foi
quebrado. O comando “break” serve também para forçar o fim dos laços com o
comando “while”. Após o laço de exclusão, repetimos o laço para exibição, assim
você poderá verificar que não existe mais o equipamento referente ao número serial
que foi excluído.
Listas e Funções

Agora observe o seguinte detalhe: se o equipamento do nosso inventário


possuir dezenas de características, teremos que criar também dezenas de listas, e
assim o código irá aumentar assustadoramente. O nosso “for”, onde utilizamos o
comando “del”, foi formado por quatro linhas para excluir o elemento. Se tivéssemos
20 listas, teríamos, então, não mais quatro linhas, mas, sim, 20 linhas, esse é
apenas um exemplo. O que poderíamos fazer para resolver isso? Simples,
poderíamos criar listas dentro de listas.

Listas dentro de listas

Conforme dito no último tópico, podemos explorar as listas também, inserindo


uma lista dentro da outra. Para isso, iremos manipular dois índices, um para se
referir à lista externa (responsável por armazenar outras listas) e outro para se referir
à lista interna (que está dentro de uma lista).
Listas e Funções

Vamos agora criar um novo arquivo no PyCharm, chamado “ListasDentroLista.py”, no qual


iremos montar o código com o mesmo objetivo do arquivo “MultiplasListas.py”, mas, dessa
vez, iremos utilizar apenas duas listas (interna e externa – equipamento e inventário,
respectivamente):
inventario=[]
resposta = "S"
while resposta == "S":
equipamento=[input("Equipamento: "),
float(input("Valor: ")),
int(input("Número Serial: ")),
input("Departamento: ")]
inventario.append(equipamento)
resposta = input("Digite \"S\" para continuar: ").upper()
Listas e Funções
for elemento in inventario:
print("Nome.........: ", elemento[0])
print("Valor........: ", elemento[1])
print("Serial.......: ", elemento[2])
print("Departamento.: ", elemento[3])
busca=input("\nDigite o nome do equipamento que deseja buscar: ")
for elemento in inventario:
if busca==elemento[0]:
print("Valor..: ", elemento[1])
print("Serial.:", elemento[2])
depreciacao=input("\nDigite o nome do equipamento que será depreciado: ")
for elemento in inventario:
if depreciacao==elemento[0]:
print("Valor antigo: ", elemento[1])
elemento[1] = elemento[1] * 0.9
print("Novo valor: ", elemento[1])
Listas e Funções
serial=int(input("\nDigite o serial do equipamento que será excluído: "))
for elemento in inventario:
if elemento[2]==serial:
inventario.remove(elemento)
for elemento in inventario:
print("Nome.........: ", elemento[0])
print("Valor........: ", elemento[1])
print("Serial.......: ", elemento[2])
print("Departamento.: ", elemento[3])

Observe o código entre os arquivos, “ListasDentroLista.py” e Situacao1.py”, "Situacao2" e


procure perceber qual está mais legível e mais simples de compreender. Caso você não
tenha uma tendência em preferir códigos mais complexos, irá perceber que o código do
arquivo “ListasDentroLista.py” se tornou mais legível que o anterior.
Com este exemplo, conseguimos perceber quanto as funções permitem
reduzir o nosso código, mas o poder das funções vai além… Seguindo ainda a
possibilidade de a função input() não existir, você acha que as 15 linhas que
deveriam ser digitadas seriam iguais entre mim, você e todos os outros
programadores de Python do mundo? Com certeza não, dentro da programação
cada um possui sua lógica e defende a sua forma de programar; desde que utilize
boas práticas, o que vale é o funcionamento do código, não é mesmo?!

Abra o nosso arquivo “ListasDentroListas.py” e tente identificar visualmente


os módulos que esse código poderia possuir. Vamos separar as funções existentes por
comentário.
Perceba que poderemos dividir significativamente o nosso código. Também
vale ressaltar que temos dois blocos de códigos idênticos, o bloco “exibir dados do
inventário”, ocupando mais linhas que o necessário. Primeiramente, iremos montar
aos poucos um novo arquivo chamado: “IdentificacaoFuncoes.py”, conforme as
funções que separamos.
Caso você possua uma lista que armazene somente valores numéricos,
poderá, então, fazer uso de algumas funções bem úteis. Adicione ao final do
código do arquivo ListasDentroLista.py, o código abaixo:
valores=[]
for elemento in inventario:
valores.append(elemento[1])
if len(valores)>0:
print("O equipamento mais caro custa: ", max(valores))
print("O equipamento mais barato custa: ", min(valores))
print("O total de equipamentos é de: ", sum(valores))

No código acima, criamos uma lista para armazenar somente os valores dos
equipamentos, preenchemos a mesma dentro do “for” e, depois de ser
preenchida, verificamos se a lista possui ao menos um valor, e, se a condição for
verdadeira, as funções abaixo serão executadas:
• “max()”: que retorna o maior valor numérico dentre os elementos da lista;
• “min()”: que retorna o menor valor numérico dentre os elementos da lista; e
• “sum()”: que retorna o total entre os valores que estão na lista.

Encerramos o nosso assunto de listas por aqui, espero que tenham gostado.
Existem mais funções que podem ser utilizadas, mas, para o propósito do curso,
este conteúdo sobre listas já é o suficiente. Observe o seu último arquivo criado…
Ficou extenso, não é mesmo? Vamos falar sobre funções ??
Funções

Até agora trabalhamos com diversas funções: int(), str(), float(), input(), print()… Todas elas
já fazem parte da linguagem Python e estão incorporadas na nossa PVM (Python Virtual
Machine). Agora vamos imaginar se, por acaso, não existissem as funções. Para facilitar,
vamos pensar em uma delas, a input(). Se ela não existisse, a todo momento teríamos que,
dentro do nosso código, montar uma sequência de outros códigos para que o usuário
pudesse digitar uma informação, isso poderia levar, por exemplo, 15 linhas. Ou seja, em vez
de utilizarmos um simples input(), deveríamos utilizar 15 linhas. Agora conte quantos
inputs utilizou em nosso último arquivo de código gerado e multiplique por 15…
Assustador, não é mesmo?!
• Para criarmos funções, utilizaremos o comando “def”, e a estrutura básica de uma função
é a seguinte:
def <identificador da funcao> (<parametro(s)>):
<código que será executado>
return <Dado que será retornado, caso seja necessário>
O parâmetro é um dado que será fornecido para que a função possa executar o seu
bloco de códigos. É como se fossem os ingredientes de uma receita, por exemplo,
para que uma função possa calcular uma média aritmética entre duas notas, você
deverá fornecer as duas notas ou ainda para que uma função calcule o salário
líquido de um colaborador,precisará informar para a função, no mínimo, o salário
bruto.
O código a ser executado representa o conjunto de códigos que possuem
uma mesma finalidade dentro da aplicação.
• A última linha de “return” é opcional e deve ser usada somente quando
você desejar que a função retorne um valor para o módulo principal.
Cientes dessas informações, vamos colocar em prática. Criaremos a primeira
função, que terá a finalidade de preencher o inventário. Por isso, iremos chamá-la
de preencherInventario(). Dentro do nosso novo arquivo
“IdentificacaoDeFuncoes.py”, digite o seguinte código:
def preencherInventario(lista):
resp="S"
while resp == "S":
equipamento=[input("Equipamento: "),
float(input("Valor: ")),
int(input("Número Serial: ")),
input("Departamento: ")]
lista.append(equipamento)
resp = input("Digite \"S\" para continuar: ").upper()

Para a nossa função preencherInventario(), recebemos um parâmetro que é a


lista na qual o módulo principal irá armazenar os itens do inventário. O nome
fornecido ao parâmetro (no nosso caso, “lista”) não tem qualquer relação com a lista
que será criada no módulo principal.

Tente executar o arquivo IdentificacaoDeFuncoes.py


Durante a montagem das funções, muito cuidado com as tabulações. Tente
você, agora, montar o código da nossa segunda função: exibirInventario(). Monte o
código dessa função imediatamente abaixo da função anteriormente criada
(preencherInventario()). Seu código deverá ficar semelhante ao código abaixo:

def preencherInventario(lista):
resp="S"
while resp == "S":
equipamento=[input("Equipamento: "),
float(input("Valor: ")),
int(input("Número Serial: ")),
input("Departamento: ")]
lista.append(equipamento)
resp = input("Digite \"S\" para continuar: ").upper()
def exibirInventario(lista):
for elemento in lista:
print("Nome.........: ", elemento[0])
print("Valor........: ", elemento[1])
print("Serial.......: ", elemento[2])
print("Departamento.: ", elemento[3])

A nossa função “exibirInventario()”irá receber a lista, por parâmetro, e, então,


executará o laço “for” para exibir os dados da lista recebida. Nessa função, não
precisamos de return, uma vez que as informações já estão sendo “printadas”.
Agora, cabe a você tentar montar as outras funções conforme as marcações que
fizemos no início deste tópico.
Tente criar as funções: localizarPorNome(), depreciarPorNome(),
excluirPorSerial() e resumirValores(). Abaixo, o código da função
localizarPorNome():
def localizarPorNome(lista):
busca=input("\nDigite o nome do equipamento que deseja buscar: ")
for elemento in lista:
if busca==elemento[0]:
print("Valor..: ", elemento[1])
print("Serial.:", elemento[2])

def depreciarPorNome(lista, porc):


depreciacao=input("\nDigite o nome do equipamento que será depreciado: ")
for elemento in lista:
if depreciacao==elemento[0]:
print("Valor antigo: ", elemento[1])
elemento[1] = elemento[1] * (1-porc/100)
print("Novo valor: ", elemento[1])
A função depreciarPorNome() apresenta dois parâmetros: um deles é a lista
na qual estão os equipamentos que sofrerão a depreciação; e o outro é a
porcentagem que se deseja depreciar. Repare que a fórmula matemática foi alterada
quando comparada com o arquivo anterior
def excluirPorSerial(lista):
serial=int(input("\nDigite o serial do equipamento que será excluido: "))
for elemento in lista:
if elemento[2]==serial:
lista.remove(elemento)
return "Itens excluídos."
A função excluirPorSerial() retorna uma string, ou seja, quando formos
chamar essa função, devemos fazê-la dentro de um comando print(), para que
possamos ver a mensagem.
def resumirValores(lista):
valores=[]
for elemento in lista:
valores.append(elemento[1])
if len(valores)>0:
print("O equipamento mais caro custa: ", max(valores))
print("O equipamento mais barato custa: ", min(valores))
print("O total de equipamentos é de: ", sum(valores))

E para finalizar, a função resumirValores() poderia ser facilmente dividida em


três funções: somar(), exibirMaiorValor() e exibirMenorValor(), tudo depende muito
do contexto e da especificação que se deseja obter. Para o nosso exemplo,
manteremos apenas como uma função que realiza as três tarefas
Pronto??? Ainda não, agora que já temos as nossas funções, podemos montar o nosso
módulo principal a fim de chamá-las e testá-las para checarmos se está tudo correto. Para
isso, vamos seguir as seguintes etapas:
• Crie um “Python Package”, cuja função é apontar para o PyCharm um pacote em que
teremos arquivos que poderão ser importados por outros projetos. Para criá-lo, clique com
o botão direito sobre Capitulo3, selecione a opção New/Python Package e atribua o nome
Funcoes.
Repare que, dentro do pacote gerado, foi criado um arquivo chamado “__init__.py”. Não
discutiremos sobre esse arquivo agora e ele também não nos será útil. Por isso, você pode
excluí-lo. Agora, vamos criar um novo arquivo, dentro do diretório Capitulo3, chamado
“ModuloPrincipal.py”.. Dentro dele, devemos utilizar dois novos comandos, que
normalmente são utilizados em conjunto, identificados como “from” e “import”.
O “from” deverá receber o local físico no qual se encontram as funções que se deseja
importar. Já no “import”, você deverá definir qual ou quais funções deseja importar. Se
utilizar um asterisco “*”, ele importará todas as funções contidas no “from”, conforme
podemos perceber na primeira linha do código do nosso módulo principal abaixo:

from Capitulo3.IdentificacaoFuncoes import *


minhaLista=[]
print("Preenchendo")
preencherInventario(minhaLista)
print("Exibindo")
exibirInventario(minhaLista)
print("Pesquisando")
localizarPorNome(minhaLista)
print("Alterando")
depreciarPorNome(minhaLista, 20)
print("Excluindo")
print(excluirPorSerial(minhaLista))
exibirInventario(minhaLista)
print("Resumindo")
resumirValores(minhaLista)

Ficou muito mais clean a leitura do módulo principal, não é mesmo? Repare
que somente a função excluirSerial() foi chamada dentro do print(), isso porque
somente ela possui retorno. Veja também a economia de linhas quando apenas
chamamos duas vezes a função exibirInventario(), em vez de repetir todas as linhas
que estão dentro dessa função. E vamos pensar na hipótese das centenas de filiais
que podem aparecer, cada uma com sua necessidade. Não será problema algum
agora, pois passaremos o nosso módulo e a filial irá reaproveitar as funções que
desejar, assim, não teremos que ficar separando linhas.
Manipulação de Dados e Tupla

Uma das estruturas mais flexíveis do Python, é o dicionário de dados, que,


assim como as listas foram exploradas no capítulo anterior, deve ser utilizado
com dados voláteis em memória. Vamos ver as diferenças entre um dicionário
e uma lista, e quais as situações mais recomendadas para utilização dos dicionários.
E, por fim, comentamos sobre as tuplas, a última estrutura de dados que veremos
no curso, para dados voláteis.

De acordo com o seu projeto para a clínica, vamos pensar na seguinte


situação: você, com certeza, já pensou em grupos de usuários e os seus níveis de
permissionamento. Imagine que você vai gerar uma fonte, representada por um
arquivo que será controlado por sua aplicação, e nele encontrará informações sobre
as ações dos usuários, entretanto, realizar essa leitura diretamente no arquivo não é
nada prático e tampouco rápido.
Manipulação de Dados e Tupla
Eis que surge a ideia de desenvolver uma ferramenta capaz de realizar, além da inserção
dos dados, a leitura dos dados e retorná-los de tal forma que você obtenha as informações
necessárias e resumidas e possa tomar as suas decisões de gerenciamento e segurança do
ambiente, de maneira rápida, com eficiência e eficácia.
Considere:

Usuario 1: Login - Chaves, Nome - Chaves Silva, Último Acesso: 17/05/2023, Estação: Recep_01
Usuário 2: Login - Quico, Nome - Enrico Flores, Último Acesso: 03/05/2023, Estação: Raiox_02

Vamos iniciar considerando apenas os dados encontrados acima, ou seja, todo usuário
(colaborador da clínica) terá registrado um login (que é único, porque não podemos ter dois
usuários com o mesmo login), nome, a data do último acesso (futuramente poderemos
pensar na hora também, e a estação que ele logou pela última vez). Alguns outros dados
parecem ser importantes a fim de complementarmos o registro do usuário como: cargo,
departamento, nível de acesso (usuário, administrador, gerente etc.), entre outros, mas, no
momento, vamos adotar apenas estes para fins didáticos.
Manipulação de Dados e Tupla

Você precisa, a princípio, pensar em uma estrutura que receba os dados dos usuários para
que você possa examiná-los, a fim de identificar alguma “anomalia”, por exemplo, um
usuário que aparece acessando uma estação que está em um departamento que ele não
atua ou um último acesso localizado em uma data em que o departamento dele não abriu
oficialmente. Você pensaria em criar uma estrutura através de lista?

Pois é, essa não seria a situação mais indicada para as listas. Por quê? Vamos ver um dos
motivos: se pensarmos em uma lista para cada usuário, quantas listas exatamente
precisaremos criar no código? Não conseguiremos definir, pois o número de
colaboradores não é fixo e podemos ter mais ou menos do que planejado, por falta, férias,
folga, novas contratações, entre outras possibilidades.
Manipulação de Dados e Tupla
Então, você pensa em criar uma lista para colaboradores e, dentro dela, outras listas que
irão armazenar os dados efetivamente de cada colaborador. Mas, pense... cada vez que o
usuário logar em uma estação, os dados deverão ser atualizados (data do último acesso e
a última estação acessada), ou seja, como em listas você não tem como localizar um dado
diretamente, você terá que percorrer (estruturas de repetição) toda a lista todas as vezes
que todos os colaboradores realizarem um logon.

Como você já pode imaginar, teremos que utilizar, na situação anteriormente


proposta, os dicionários de dados, mas, antes, vamos ver como eles são formados e
como funcionam.
Um dicionário armazena elementos. De agora em diante, vamos chamar
estes elementos de objetos. Cada objeto será dividido em duas partes: chave e dados. A
chave é um dado único e exclusivo do elemento. Todo elemento deverá ter
uma chave. Através dela, vamos identificar quem é o objeto e, consequentemente,
poderemos visualizar os seus dados.
Manipulação de Dados e Tupla
O objeto “usuário” possui alguma chave? Se observar bem, quando
descrevemos a situação proposta, explicamos que o “login” é um dado único, ou
seja, ele poderá ser a chave do objeto “usuário”, uma vez que nunca teremos dois
usuários com o mesmo login. Podemos também dizer que nunca teremos dois
objetos com a mesma chave login em nosso dicionário. Podemos dar outros
exemplos para que você entenda o valor de uma chave em um dicionário.

Para a Receita Federal, cada pessoa física é um objeto que possui vários
dados: nome, endereço, CPF, RG, estado civil, telefone, entre outros. Qual entre
estes dados representa um único objeto, ou seja, uma única pessoa física para a
Receita Federal? Isso mesmo, o CPF. Ele é único para cada pessoa física e com
isso, poderia ser a chave. Outro exemplo: um ativo de rede, dentro da clínica, deverá
fazer parte de um inventário e, por isso, será necessário guardar dados sobre ele,
como: descrição, modelo, fabricante, valor de compra, data da aquisição, entre
outros.
Manipulação de Dados e Tupla
Agora podemos ver como representaremos os dicionários dentro do Python. Abra o nosso
projeto e, consequentemente, crie um Python Package.
Atribua para este pacote o nome: “Capitulo4_Dicionarios” e crie um arquivo python com
nome Dicionarios1.py
Dentro do arquivo criado, monte o código abaixo:
usuarios={}
usuarios={
"Chaves":["Chaves Silva","17/06/2017","Recep_01"],
"Quico":["Enrico Flores","03/06/2017","Raiox_02"]}

Na primeira linha, estamos criando o dicionário de dados. Repare que, em vez de


utilizarmos os colchetes (como fizemos com as listas), usamos as chaves “{}”, essa é a
representação de um dicionário de dados. Copie a linha abaixo:
Manipulação de Dados e Tupla
Na segunda linha, preenchemos fielmente o nosso dicionário de acordo com o
nosso exemplo de um dicionário de dados. Acima, perceba que adotamos os logins
como chave de cada objeto (no caso, são dois). Depois da chave, utilizamos dois
pontos (:) e, então, surgem os dados da chave que foi preenchida. Como no exemplo, o
login “Chaves” possui mais de um dado, optamos em criar uma lista para
armazenar estes dados e, dentro desta lista, colocamos o nome, a data de último
acesso e o nome da última estação onde esteve logado. Após a vírgula (,) iniciamos
o outro objeto, com a chave “Quico”, seguido de dois pontos (:) e, então, a lista com
os dados deste objeto. E aí encerramos o dicionário, fechando as chaves. Se, por
um engano, você colocar dois objetos com a mesma chave, o segundo objeto irá
sobrescrever o primeiro. Também podemos adicionar itens no dicionário da seguinte
forma:

usuarios["Florinda"]=["Florinda Flores", "26/11/2022", "Recep_01"]


Manipulação de Dados e Tupla
A linha acima apresentada normalmente é utilizada quando queremos
adicionar os objetos de maneira singular, ou seja, objeto por objeto. Repare que,
após o nome do dicionário, colocamos entre colchetes do dado que será
armazenado na chave e igualamos com o dado que pertence à chave. No nosso
caso, uma lista com nome, data do último acesso ao sistema e a última estação que
foi utilizada pelo usuário. Da primeira forma que foi apresentada (no Código-fonte:
“Exemplo de um dicionário de dados”), se tentarmos dividir em dois momentos a
adição dos objetos no dicionário, simplesmente estaremos considerando a última
linha onde foi inserido o conteúdo, sobrescrevendo todos os objetos inseridos
anteriormente.
Caso repita a mesma linha do Código-fonte: “Adicionando um objeto no
dicionário”, isto é, se tentar usar a mesma chave, o código não irá gerar erros ou
exceções, mas o objeto que estiver na segunda linha irá sobrescrever o objeto que
estava na primeira linha. Segue abaixo um código para exemplificar:
Manipulação de Dados e Tupla
usuarios={}
usuarios={
"Chaves":["Chaves Silva","17/06/1975","Recep_01"],
"Quico":["Enrico Flores","03/06/1976","Raiox_02"],
"Quico":["Enrico Flores","03/06/1976","Raiox_03"]
}
usuarios["Florinda"]=["Florinda Flores", "26/11/2017", "Recep_01"]
usuarios["Florinda"]=["Florinda Flores", "26/11/2016", "Recep_01"]

chave “Quico” (que teve como último acesso a estação “Raiox_03”) e o último com a
chave “Florinda” (com a data “26/11/2016” atribuída ao último acesso).
Veremos agora como podemos retornar os dados de um objeto da lista,
acrescente no seu código as linhas abaixo:
Manipulação de Dados e Tupla
Veremos agora como podemos retornar os dados de um objeto da lista, acrescente no seu
código as linhas abaixo:

print(usuarios)
print("##############========#########")
print("Dados: ",usuarios.get("Chaves"))

No primeiro print(), exibimos tudo o que existe dentro do dicionário. Já no


último print(), somente os dados do objeto que tiver a chave “Chaves”. Isso foi
possível porque invocamos o nosso dicionário “usuarios” e utilizamos o seu método
get(), que recebe um dado e vai pesquisá-lo entre as chaves que existem dentro do
dicionário, caso ele encontre, retornará os dados relativos à chave encontrada.

Podemos agora resolver a questão da nossa ferramenta que vai armazenar


os dados dos usuários dentro dos dicionários e realizar as devidas alterações e
possíveis exclusões. Vamos começar criando um arquivo, chamado:
“ManagerUsers.py” e iniciar perguntando ao usuário o que ele deseja realizar:
inserir, pesquisar, excluir, listar ou sair.
Manipulação de Dados e Tupla
usuarios={}
opcao=input("O que deseja realizar?\n" +
"<I> - Para Inserir um usuário\n"+
"<P> - Para Pesquisar um usuário\n"+
"<E> - Para Excluir um usuário\n"+
"<L> - Para Listar um usuário: ").upper()
while opcao=="I" or opcao=="P" or opcao=="E" or opcao=="L":
if opcao=="I":
chave=input("Digite o login: ").upper()
nome=input("Digite o nome: ").upper()
data=input("Digite a última data de acesso: ")
estacao=input("Qual a última estação acessada: ").upper()
usuarios[chave]=[nome, data, estacao]
opcao = input("O que deseja realizar?\n" +
"<I> - Para Inserir um usuário\n" +
"<P> - Para Pesquisar um usuário\n" +
"<E> - Para Excluir um usuário\n" +
"<L> - Para Listar um usuário: ").upper()
Manipulação de Dados e Tupla
O código acima apresenta alguns pontos a serem melhorados. Olhe-o com
criticidade e identifique algumas falhas. Antes de apontá-las, vamos descrever o que
está ocorrendo: criamos um dicionário chamado “usuarios” e uma variável chamada
“opcao”, que vai armazenar, em caixa alta, o que o usuário deseja fazer. Para as
letras “I”, “P”, “E” ou “L”, o código vai realizar uma ação, para qualquer outro valor, o
código será encerrado.

Vamos trocar as 5 linhas abaixo:


chave=input("Digite o login: ").upper()
nome=input("Digite o nome: ").upper()
data=input("Digite a última data de acesso: ")
estacao=input("Qual a última estação acessada: ").upper()
usuarios[chave]=[nome, data, estacao]

Pelas linhas a seguir:


chave=input("Digite o login: ").upper()
usuarios[chave]=[input("Digite o nome: ").upper(), input("Digite a última data de acesso: "),
input("Qual a última estação acessada: ").upper()]
Manipulação de Dados e Tupla
Economizamos, assim, três variáveis em memória, e talvez você esteja se
perguntando, mas por que não fazer o mesmo com a chave? Assim, não
precisaríamos de nenhuma variável, não é mesmo? Sim, você está correto, mas
optei em deixar a variável-chave, pois caso eu coloque o input dentro dos colchetes
da chave, ele será preenchido por último, pois o Python resolverá primeiro o que
está depois do sinal de igual, ou seja, ele pediria o nome, a data, a estação e, por
último, o login. Acredito que a ordem ficaria um tanto quanto desconexa, ou seja, uma
simples questão de estética para o usuário final. Caso isso não seja um problema
para você, pode economizar a variável-chave e colocar tudo em uma única linha,
conforme está demonstrado no seguinte código:

usuarios[input("Digite o login: ").upper()]=[input("Digite o nome: ").upper(),


input("Digite a última data de acesso: "),
input("Qual a última estação acessada: ").upper()]
Manipulação de Dados e Tupla
Conforme o código: sem o uso de variável, acima, estaríamos substituindo,
então, cinco linhas, por apenas, uma linha. Melhor, não é mesmo? Mas caso nesse
momento ainda se sinta mais confortável criando as variáveis, não tem problema.
Neste ponto, o importante é conseguir desenvolver. Com o passar do tempo e com
uma intimidade maior com a linguagem, você começará a desenvolver códigos mais
enxutos.
Mas, ainda temos algo “feio” dentro do nosso código, algo bem visível.
Encontrou? Vamos lá, temos uma linha enorme sendo utilizada duas vezes, a linha
onde você preenche o conteúdo da variável “opção”, assim seu código não está
elegante, alguém por aí lembra o que devemos fazer quando repetimos muito um
mesmo conjunto de código?
Mãos à obra. Crie mais um arquivo Python chamado “Funcoes.py” e, dentro dele, digite o
código abaixo
Manipulação de Dados e Tupla
def perguntar():
resposta = input("O que deseja realizar?\n" +
"<I> - Para Inserir um usuário\n" +
"<P> - Para Pesquisar um usuário\n" +
"<E> - Para Excluir um usuário\n" +
"<L> - Para Listar um usuário: ").upper()
return resposta
def inserir(dicionario):
dicionario[input("Digite o login: ").upper()] = [input("Digite o nome: ").upper(),
input("Digite a última data de acesso: "),
input("Qual a última estação acessada: ").upper()]

O código acima representa duas funções. A primeira que perguntará ao


usuário e, então, retornará a resposta do usuário; e a segunda que receberá um
dicionário (parâmetro que está entre parênteses “()”) e, então, inserirá um objeto
dentro deste dicionário. Agora, tente implementar as duas funções no seu arquivo
“ManagerUsers.py”. Veja se ficará semelhante ao código abaixo:
Manipulação de Dados e Tupla
from Capitulo4_Dicionarios.Funcoes import *
usuarios={}
opcao=perguntar()
while opcao=="I" or opcao=="P" or opcao=="E" or opcao=="L":
if opcao=="I":
inserir(usuarios)
opcao = perguntar()

Veja como o código ficou muito mais limpo, neste que será o nosso módulo
principal. Não se esqueça de fazer a importação, que está na primeira linha do
código. Agora, nos resta montar as outras funções e implementá-las dentro deste
módulo principal. Topa o desafio? Abra o seu arquivo “funcoes.py” e crie as funções:
pesquisar() – dica: você precisará receber como parâmetro a chave e o dicionário,
excluir() – dica: você precisará utilizar o comando “del”, e listar(). Depois volte para o
material e confira o seu código, com a nossa proposta logo abaixo:
Manipulação de Dados e Tupla
def pesquisar(dicionario, chave):
lista = dicionario.get(chave)
if lista is not None:
print("Nome...........: " + lista[0])
print("Último acesso..: " + lista[1])
print("Última estação.: " + lista[2])

def excluir(dicionario, chave):


if dicionario.get(chave) is not None:
del dicionario[chave]
print("Objeto Eliminado")

def listar(dicionario):
for chave, valor in dicionario.items():
print("Objeto......")
print("Login: ", chave)
print("Dados: ", valor)
Manipulação de Dados e Tupla
O código acima é responsável por criar as outras três funções. Observe
alguns detalhes:
• Na função pesquisar(), precisamos receber o dicionário (onde se pretende
pesquisar) e a chave (o dado que será pesquisado). Logo após, vamos
preencher uma lista com o resultado da pesquisa proveniente do uso da
função get(). Verificamos se a lista não está vazia (!= - representa
diferente), caso esta condição seja verdadeira, vamos exibir os três dados
que compõem a lista. Teremos, na primeira posição (zero), o nome do
usuário; na segunda posição (um), a última data de acesso; e na terceira
posição (dois), a última estação acessada. Caso não encontre a chave,
não será retornada nenhuma mensagem;

Na função excluir(), também recebemos o dicionário de onde o objeto será


excluído e a chave do objeto que se deseja excluir. Efetivamente, antes da
exclusão, devemos verificar se a chave existe. Por isso, verificamos com a
função get() se será retornado algo diferente de vazio e, se isso for
verdade, invocamos o comando “del”, que eliminará o objeto de acordo
com a chave que foi recebida.
Manipulação de Dados e Tupla
Na função listar(), precisaremos apenas do dicionário que contém os
dados que desejamos exibir, com isso, montamos um foreach, mas
perceba que, desta vez, utilizamos dois valores (chave e valor) para que
possamos dar uma saída um pouco mais “clean” para o nosso usuário
final. Poderíamos fazer de outras formas, inclusive, utilizando a nossa
outra função pesquisar().
Agora nos resta implementar as nossas funções dentro do módulo principal,
ou seja, dentro do arquivo “ManagerUsers.py”, conforme apresentado abaixo (vale
tentar implementar antes de verificar o código abaixo):

from Capitulo4_Dicionarios.Funcoes import *


usuarios={}
opcao=perguntar()
while opcao=="I" or opcao=="P" or opcao=="E" or opcao=="L":
if opcao=="I":
inserir(usuarios)
if opcao=="P":
pesquisar(usuarios,input("Qual login deseja pesquisar? "))
Manipulação de Dados e Tupla
if opcao == "E":
excluir(usuarios,input("Qual login deseja excluir? "))
if opcao == "L":
listar(usuarios)
opcao = perguntar()

E está aí tudo pronto e funcional, fácil, não é mesmo? Você deve estar se
perguntando, por que não realizamos uma função para alterar os dados de um
objeto já armazenado na lista? Simples, caso o usuário final digite ao incluir uma
mesma chave, todos os dados que ele inserir vão sobrescrever os dados do objeto
que já estavam armazenados, logo, não se faz necessário nesse momento uma
função para realizar alterações.

Os dicionários possuem alguns métodos que podem ser úteis em outras


situações do dia a dia, vamos explorar alguns deles:
Manipulação de Dados e Tupla
items(): responsável por retornar em forma de lista os elementos do
dicionário. Para isso, ele fará uso do recurso de tuplas, que será
apresentado no tópico seguinte. Basicamente, cada tupla terá uma chave
e um dado, conforme podemos perceber no exemplo abaixo.
Considerando nosso exemplo, poderíamos ter este método retornando os
dados da seguinte forma:
[(“ologin”,[“nome”,”data”,”estacao”]),(“login2”,[“nome2”, “data2”,”est2”])]
Perceba que temos a lista e, dentro da lista, dois elementos entre
parênteses (cada elemento é uma tupla) e, dentro de cada elemento, dois
elementos, a chave (login) e o dado (lista com nome, data e estação).
Este método é muito utilizado em foreachs, como podemos perceber no
método listar() que criamos anteriormente.
• values(): podemos retornar também somente os dados, descartando as
chaves, ou seja, esse método retorna uma lista formada apenas pelos
dados. Se pegarmos como exemplo o nosso caso do histórico dos
usuários, teremos uma lista dentro de outra lista, e o exemplo ficaria como
o que está apresentado abaixo:
[ [“nome”,”data”,”estacao”],[“nome2”, “data2”,”est2”]]
Manipulação de Dados e Tupla
keys(): claro que se retornarmos somente os dados, podemos retornar
também somente as chaves. E é isto o que este método faz, retornando
todas as chaves do dicionário em forma de lista, conforme apresentado na
linha abaixo:
[“ologin”, “login2”]
• has_key(): este método permitirá que você tenha a resposta se a chave
existe ou não dentro do dicionário, ele irá retornar True (1) ou False (0).
• clear(): esvazia completamente o dicionário.
• popitem(): este é um método próprio para quem deseja montar algum
dicionário que contenha elementos que serão executados, de maneira
aleatória, individualmente e, na sequência, deverão ser eliminados do
dicionário. Poderíamos pensar em um dicionário com dicas, e à medida
que cada dica fosse exibida, automaticamente ela deveria ser retirada do
dicionário.
Enfim, estes são alguns métodos que, em eventuais e particulares
circunstâncias, podem ser necessários e, então, utilizados. Estes métodos também
podem ser apontados como diferenciais quando comparamos listas com dicionários.
Manipulação de Dados e Tupla
Para praticar um pouco, procure aperfeiçoar o nosso exemplo
ManagerUsers.py, inserindo mais dados que podem ser importantes para o seu controle.
Você acredita que o “nome de login” realmente seria um dado único para a
situação de controle com base nos logs que seriam gerados, nas estações, a cada
login?

Tuplas

As tuplas, como já dissemos, são estruturas também para dados voláteis,


assim como as variáveis, listas e dicionários. Porém, você percebeu que cada uma
possui as suas devidas aplicações, e com as tuplas não poderia deixar de ser
diferente.
Uma característica única das tuplas é o fato de elas não aceitarem alteração
sobre os dados que já estiverem nelas inseridos. Além disso, as tuplas sempre são
representadas com seus dados entre parênteses. Então, podemos sintetizar que:
listas envolvem os dados entre colchetes; dicionários entre chaves; e tuplas entre
parênteses.
Manipulação de Dados e Tupla
Veremos a seguir a manipulação básica dos dados que podem ser inseridos e
recuperados em uma tupla. Vamos iniciar criando um arquivo chamado: “Tupla.py”
(no próprio Python Package do Capítulo 4), e, então, digitaremos o código abaixo:

ips={}
resp="S"
while resp=="S":
ips[(input("Digite os dois primeiros octetos: "),
input("Digite os dois últimos octetos: "))]=input("Nome da máquina: ")
resp=input("Digite <S> para continuar: ").upper()

Como podemos observar no código, criamos um dicionário chamado “ips”,


uma variável chamada “resp” para controlar o nosso laço e, dentro do laço de
repetição, vamos preencher o nosso dicionário, mas perceba que, na chave do
dicionário, inserimos dois valores. A primeira parte do ip e a segunda parte do ip,
dentro de uma tupla, e o dado do elemento que está sendo adicionado no dicionário
é o nome da estação.Vejamos agora como aproveitar os dados da chave no formato de
tupla. Adicione o código abaixo:
Manipulação de Dados e Tupla
print("Exibindo ip´s: ")
for ip in ips.keys():
print(ip[0]+"."+ip[1])

No código abaixo, vamos pedir ao usuário a segunda parte do ip (dois últimos


octetos), isto é, o endereço da máquina, para, então, exibirmos o nome das
máquinas que estão sob o mesmo endereço, mas em redes diferentes (baseado nos
dois primeiros octetos). Perceba que está se tornará uma tarefa simples, pois a
nossa chave já está desmembrada, facilitando muito a recuperação do dado.
Adicione agora o código abaixo:

print("Exibindo máquinas com o mesmo endereço: ")


pesquisa=input("Digite os dois últimos octetos: ")
for ip,nome in ips.items():
print("Máquinas no mesmo endereço (redes diferentes)")
if(ip[1]==pesquisa):
print(nome)
Manipulação de Dados e Tupla
Avaliando o código acima, vemos a solicitação do dado para o usuário e o
armazenamento deste dado na variável pesquisa. Em seguida, na linha onde
definimos o nosso laço “for”, vamos recuperar dois dados ip e o nome da máquina,
que serão retornados pelo método items(); Depois, exibimos uma mensagem para o
usuário e fazemos a comparação da parte dois do ip (dois últimos octetos) com o
que o usuário digitou na variável pesquisa. Caso eles sejam iguais, exibimos o nome
da máquina. Agora tente fazer o seguinte: gostaríamos de saber quais estações
compõem uma rede. Para isso, iremos nos basear nos dois primeiros octetos do ip.
Procure fazer este código e depois compare com o código abaixo:

print("Exibindo as máquinas que compõem uma mesma rede: ")


rede=input("Digite os dois primeiros octetos: ")
for ip,nome in ips.items():
if(ip[0]==rede):
print(nome)
Manipulação de Dados e Tupla
Desta vez, de acordo com o código acima, pedimos os dois primeiros octetos
para o usuário e montamos o laço “for” recebendo os dois valores do dicionário (chave e
dado). Como a chave é uma tupla formada por dois valores, utilizamos o
primeiro valor para comparar com o conteúdo da variável “rede”. Caso sejam iguais,
vamos exibir os nomes das estações que compõem ou que estão “penduradas” na
rede que foi especificada pelo usuário. O importante, neste momento, é perceber que as
duas operações foram simples e utilizamos pouco código devido ao dado “ip” estar
desmembrado dentro da tupla. Se o dado do dicionário fosse uma lista (como no exemplo
dos usuários), teríamos todas as estruturas em um só exemplo; variáveis, listas, tuplas e
dicionários, é assim que elas devem ser utilizadas, dentro das suas características e
utilizando o que cada uma tem de melhor. Você não pode, dentro da programação,
querer utilizar apenas uma ou outra estrutura, pois cada uma tem um papel
específico que cabe melhor, de acordo com o contexto em que será implementada.
Manipulação de Arquivos e JSON
Até o momento, nossos dados só existiam enquanto o sistema estivesse
aberto e/ou a sua estrutura não fosse limpa ou sobrescrita. A partir de agora, nossos
dados passam a ser mais valorizados pelas nossas rotinas e, então, iremos persistir
esses dados em disco. Isso significa que eles passarão a existir fisicamente em uma
estrutura de arquivo, o que irá permitir que você transporte os dados coletados de
uma máquina para outra, ou até mesmo que atualize um sistema por meio das
instruções encontradas em arquivos gerados por outros.
Também será possível gerar um arquivo de script e atualizar a configuração
de equipamentos como roteadores e switches, avaliar arquivos de log a fim de
encontrar informações sobre comportamentos não autorizados de usuários, realizar
auditorias, entre muitas outras possibilidades. Serão apresentadas ainda, algumas
funções para a manipulação de Strings de suma importância também para a
manipulação de um arquivo já gerado.
Manipulação de Arquivos e JSON
Manipulação de arquivos
Para a manipulação dos arquivos, utilizaremos uma função denominada
“open()”, que permite várias ações:

• open(“<caminhoDoArquivo><nomeDoArquivo>”, “w”) => indica que


você está abrindo um arquivo para o modo de escrita (w => write), ou seja,
permite que você escreva nele, caso o arquivo já exista, ele será
sobrescrito. É como se você adquirisse um novo “caderno”,
completamente em branco.

• open(“<caminhoDoArquivo><nomeDoArquivo>”, “r”) => com a letra “r”


(read) no segundo parâmetro da função, você abrirá o arquivo somente em
modo de leitura, isso permite que outra pessoa, em outro computador,
possa abrir esse arquivo para edição, mas você poderá apenas “consumir”
os dados que estiverem dentro desse arquivo. Nesse caso, podemos fazer a analogia com
um livro, ou seja, você não irá preenchê-lo, tão pouco
alterá-lo, apenas irá fazer a leitura.
Manipulação de Arquivos e JSON
open(“<caminhoDoArquivo><nomeDoArquivo>”, “a”) => dessa forma,
você poderá ler e escrever no arquivo especificado, como se fosse um
diário, no qual você irá acrescentando conteúdos de acordo com algum
evento, periodicidade ou qualquer outro advento do dia a dia, mas sempre
no final do diário, ou seja, a principal ideia é seguir concatenando os
dados, por isso, a letra “a” referindo-se à “append” (anexar). Um exemplo
bem prático para isso seria o controle de um arquivo de log, tudo o que for
adicionado será acrescentado ao final dos dados que já existem.

open(“<caminhoDoArquivo><nomeDoArquivo>”, “x”) => permite criar


um novo arquivo em modo exclusivo (eXclusive), ou seja, uma vez que
você criou/abriu o arquivo, ninguém mais poderá abri-lo. Caso você tente
abrir um arquivo que já existe, será retornada uma falha.
• open(“<caminhoDoArquivo><nomeDoArquivo>”, “t”) => o arquivo que
for aberto com o parâmetro “t” (text) irá retornar para o Python o seu
conteúdo como string, diferentemente do parâmetro “b”, que retornaria os
dados em formato binário e exigiria uma conversão para string, caso fosse
necessário.
Manipulação de Arquivos e JSON
Criando um arquivo e adicionando conteúdos
Para começarmos, vamos criar uma rotina que irá gerar um arquivo, veremos
alguns procedimentos simples e, então, ao término do capítulo, nos aprofundaremos
um pouco mais. Começaremos montando nossa estrutura, ou seja, dentro do
PyCharm, crie um novo “Python Package” e atribua ao mesmo o nome:
“ManipulaArquivos”. Após isso, gere dentro dele um novo arquivo Python denominado:
“GravarArquivo.py”,

Nesse arquivo, iremos montar o código abaixo. Quando for executá-lo, ele
não irá funcionar, explicaremos no parágrafo seguinte:

with open("teste.txt", "r") as arquivo:


conteudo = arquivo.read()

Para um primeiro teste, apresentamos a utilização da função open() junto ao


comando “with”, esse comando permitirá representar, dentro do bloco identado, o
arquivo “teste.txt” por meio do “alias” arquivo.
Manipulação de Arquivos e JSON
Outra grande vantagem que obteremos todas as vezes que formos utilizar a função open()
combinada ao comando with é que o controle do encerramento do arquivo em memória
ficará por conta do comando with, isso faz com que você não precise utilizar o método
close(), tampouco ocorrerá o fato do arquivo ficar aberto na memória sem qualquer
necessidade. Por isso, recomendo que utilize esse combinado open() + with, você
não vai se arrepender!
Seguindo a leitura do código apresentado anteriormente, perceba que
colocamos, no primeiro parâmetro da função open(), o arquivo “teste.txt” sem
qualquer caminho sendo especificado. Isso indica que o Python irá considerar o
caminho do seu arquivo que contém o código-fonte e que, consequentemente,
estará sendo executado, ou seja, o caminho adotado para o arquivo “teste.txt” será o
mesmo do arquivo “GravarArquivo.py”.

No segundo parâmetro, estamos especificando o valor “r”, que significa que


abriremos o arquivo somente para leitura e, dentro do with, chamamos a função
read(), que lê o conteúdo do arquivo.
Manipulação de Arquivos e JSON
Mas como você pode observar, foi gerado um
erro ao tentar executar essas duas linhas de código. Isso aconteceu porque o
arquivo não existe, como você pode tentar efetuar a leitura de um arquivo sem que
ele exista? O Python, então, retornará a mensagem de erro: FileNotFoundError:
[Errno 2] No such file or directory: 'teste.txt'. Isso foi apenas para que você
pudesse já observar o funcionamento do segundo parâmetro, uma vez que a ideia
principal, nessa parte, é a de criar um arquivo e não a de ler o arquivo.

Vamos alterar o código para:


with open("teste.txt", "w") as arquivo:
arquivo.write("Nunca foi tão fácil criar um arquivo.")

Dois pontos a serem observados:


• Alteramos o segundo parâmetro de “r” para “w”, ou seja, agora o arquivo
será aberto para escrita e não leitura.
• Dentro do with, não estamos mais utilizando o método read() e, sim, o
método write(), que nos permite passar o conteúdo que queremos para
dentro do arquivo.
Manipulação de Arquivos e JSON
Você deve estar se perguntando: mas, se o arquivo “teste.txt” não existe, o
que irá ocorrer? Execute o arquivo e veja... Agora funcionou, certo? Isso ocorreu
devido à função do parâmetro “w”, que cria o arquivo, se você executar novamente,
com outra mensagem, verá que o arquivo anterior foi sobrescrito e repare que o
arquivo foi criado junto ao seu arquivo de código.
Repare que os acentos podem estar com caracteres estranhos, isso pode ou
não acontecer, depende da configuração da sua IDE (PyCharm) para a leitura de
encodes para exibição de caracteres do tipo texto. Clique em “Reload in another
encoding” e opte pela opção windows-1252, ou ainda algum outro
encoding compatível com o seu layout de teclado, idioma e/ou sistema operacional.
Pode alterar o encode, fechar o arquivo, gerar um novo arquivo (executando seu
código) e abri-lo novamente para verificar se a alteração foi realizada com sucesso.
Agora, perceba que, ao colocarmos duas linhas com o método write(), o
conteúdo das duas linhas será adicionado no arquivo, mas se utilizarmos novamente
o método “with” com o mesmo arquivo, ele irá sobrescrever o arquivo anterior
Manipulação de Arquivos e JSON
Teste o código a seguir e veja como ficará:
with open("teste.txt", "w") as arquivo:
arquivo.write("Nunca foi tão fácil criar um arquivo.")
with open("teste.txt", "w") as arquivo:
arquivo.write("\nContinuação do texto.")

Esse código irá gerar um novo arquivo e escrever “Nunca foi tão fácil criar um
arquivo”. O arquivo será encerrado, em seguida, aberto novamente e, então, a frase
“Continuação do texto” será escrita nele, mas, ao abri-lo, você irá encontrar apenas
a segunda frase, isso porque o primeiro arquivo foi sobrescrito e não concatenado.
Essa é a função da opção “a”, que podemos utilizar no segundo parâmetro, altere
somente no segundo with o “w” por “a” e veja como irá funcionar melhor agora.

Vamos abrir um novo arquivo e gerar um html simples, para que você possa ter a
noção exata do quão importante pode ser a geração de um arquivo dentro de uma
linguagem de programação. Crie um novo arquivo chamado “ArquivoHTML.py” e
monte o seguinte código:
Manipulação de Arquivos e JSON
with open("pagina.html", "w") as pagina:
pagina.write("<body> <h1> Esta é um teste para página WEB </h1>")
pagina.write("<br><h2> Abaixo seguem alguns nomes importantes para o
projeto: </h2>")
pagina.write("<h3>")
nome=""
while nome!="SAIR":
nome = input("Digite um nome ou SAIR: ").upper()
if nome!="SAIR":
pagina.write("<br>"+nome)
pagina.write("</h3></body>")

No código, utilizamos a criação do arquivo para gerarmos um arquivo html, ou


seja, um website simples (afinal, a ideia aqui não é desenvolvê-los “front end”) para
que veja quantas possibilidades é possível gerar por meio da criação de arquivos.
Podem ir desde gerar um simples arquivo texto, passando por uma página html até
mesmo criar um código que geraria mais arquivos com códigos.
Manipulação de Arquivos e JSON
Somente para que entenda de maneira simples, o HTML é desenvolvido entre tags (nome
atribuído aos seus comandos). Essas tags são abertas como o <h1> e encerradas sempre
com uma barra entre os sinais de menor e maior, como, por exemplo </h1>. Vamos às
tags que utilizamos no código apresentado:
<body>: indica o início do conteúdo que irá visualizar na página.
• <h1>: uma formatação maior para títulos e, à medida que muda o número,
a fonte vai diminuindo, por exemplo, <h2> tem uma fonte menor que <h1>,
entretanto, é maior que <h3>.
• <br>: é uma tag que não precisa ser encerrada, pois sua função é
simplesmente dar uma quebra de linha
Agora que já vimos as tags vamos analisar o nosso código: criamos um
arquivo chamado “pagina.html”, a extensão “html” é para que o arquivo seja
interpretado como uma página pelo seu browser. Logo depois, abrimos o <body> e
colocamos um título em <h1>. Em seguida, abrimos uma nova linha e digitamos um
conteúdo com formatação <h2>. Abrimos o <h3>, criamos uma variável e montamos
um laço que irá permitir digitar vários dados nessa variável.
Manipulação de Arquivos e JSON
Enquanto o seu conteúdo for diferente de “SAIR”, dentro do while, o conteúdo da variável
será escrito, na página html, somente se não for igual a “SAIR”. Após o laço while encerrar,
fecharemos a formatação <h3> e o <body>. Rode sua aplicação, digite alguns nomes
conforme for solicitado e, após encerrar a aplicação digitando “SAIR”, você terá um
arquivo chamado “pagina.html”. Para abri-lo no browser, clique sobre o arquivo com o
botão direito do mouse, escolha a opção “Open in Browser” e o browser que preferir.
Se aprender um pouquinho mais sobre HTML, já poderá gerar relatórios ou dashboards
poderosíssimos. Repare que, nesse exemplo, utilizamos apenas variáveis, imagine o que
conseguirá fazer acrescentando as listas e os dicionários de dados.

Realizando a leitura do arquivo


Já vimos como criar os nossos arquivos, então, partiremos, agora, para a leitura do arquivo
e isso será fundamental. É muito importante, em qualquer sistema computacional, o
armazenamento dos dados, mas isso não traz nada de inovador e/ou agregador ao seu
cliente, o diferencial está na leitura dos dados, que deverá trazer, para o seu cliente, dados
na forma de informações, de uma maneira simples e confiável, pois será por meio delas
que decisões gerenciais e/ou estratégicas serão tomadas.
Manipulação de Arquivos e JSON
Por isso, armazenar é importante, mas recuperar de maneira inteligente os dados é muito
mais. Vamos para uma prática simples para esquentarmos, crie um novo arquivo de
código chamado “LeituraArquivo.py” e digite o seguinte código:

with open("teste.txt", "r") as arquivo:


conteudo=arquivo.read()
print("Tipo de dado da variável",type(conteudo))
print("\nConteúdo do arquivo:\n",conteudo)

Nesse código, abrimos o arquivo, teste.txt, para leitura (“r”) e atribuímos, para
a variável “conteudo”, todo o conteúdo do arquivo (quando utilizamos o método
read()), depois, imprimimos o tipo da variável e, na última linha, imprimimos o
conteúdo do arquivo que está dentro da variável. O tipo de dado da variável
“conteudo” que será exibido é “str”, ou seja, string, isso porque, quando não
definimos o modo de saída, o valor-padrão é o “t”(text), por isso “r” ou “rt” ou “r+t”
como segundo parâmetro retornarão o mesmo tipo.
Manipulação de Arquivos e JSON
Podemos mudar para que a saída seja em bytes, para isso, substitua “r” por “rb” ou “r+b” e
execute novamente esse bloco de código; verá que não só o tipo mudará para “byte” como
também o conteúdo do arquivo a ser exibido terá uma formatação diferente, por byte. O
mais comum mesmo é fazê-lo utilizando a saída no formato texto, não é à toa que ele é a
forma-padrão.
Outra alteração simples refere-se à forma como podemos retornar o conteúdo
do arquivo. No código anterior, utilizamos a função read(), que retornará todo o
conteúdo como se fosse uma única string. Façamos o seguinte teste: substitua
read() por readlines() e execute novamente o seu código. Percebeu a diferença? A
saída da variável “conteudo” não é mais uma string e, sim, uma lista formada por
duas posições, uma para cada linha.
Será muito útil a função readlines() quando optarmos por quebrar um grande
arquivo de texto em partes, para que possamos retirar somente os dados que nos
interessarem. Por falar nisso, vamos para um exemplo prático, no qual poderemos
explorar mais ainda os conceitos, funções e métodos apresentados até o momento
Manipulação de Arquivos e JSON
Gerando uma rotina para inventário
Uma das suas atribuições dentro do projeto será a de gerir todo o inventário
de ativos que fazem parte da rede do seu cliente. É fundamental saber quantos são,
quais são e onde estão distribuídos os ativos que fizerem parte da rede. Além disso,
muitas outras informações podem ser devidamente documentadas, como licenças
de softwares, controle sobre o que deve trafegar na rede ou em partes dela, local
definido para armazenamento de dados específicos, controle de atualizações, enfim,
o gerenciamento e a segurança de uma rede, sem dúvida, começam com um
inventário gerenciado, atualizado e funcional.
Montaremos uma rotina pequena e simples, a princípio, para que possamos
praticar as técnicas para a manipulação de arquivos vistas até o momento, com uma
aplicação prática que, com certeza, fará parte das suas atribuições como um
profissional de defesa cibernética. Vamos começar criando um novo arquivo
chamado: “Inventario.py” e iremos armazenar apenas os seguintes dados: o número
patrimonial do ativo, a descrição do ativo, data da última atualização e o nome do
departamento em que está localizado.
Manipulação de Arquivos e JSON
Primeiro iremos definir uma estrutura de dados para armazená-lo; eles serão recebidos
pelo colaborador responsável por catalogar os ativos, e, então, persistiremos os dados
para um arquivo, para que possam ser recuperados, “backupeados”, alterados, excluídos e
estejam disponíveis para qualquer outra consulta que possa ser necessária
posteriormente. Utilizaremos uma estrutura de um dicionário de dados para armazená-
los enquanto estiverem na condição de dados voláteis, em que a chave será o número
patrimonial do ativo (que não pode ser repetido). Sobre essa chave, teremos uma
lista com o departamento, data da última alteração e descrição. Após a gerência dos
dados no dicionário, iremos persistir em um arquivo do tipo “csv”, que representa um
padrão de arquivo no qual os dados poderão ser abertos dentro do Excel e de outros
programas que aceitam esse tipo de arquivo. Isso irá garantir maior flexibilidade e
portabilidade sobre os dados persistidos. Agora, vamos montar o seguinte código:
inventario = {}
opcao = int(input("Digite: "
"\n<1> para registrar ativo"
"\n<2> para persistir em arquivo"
"\n<3> para exibir ativos armazenados: "))
Manipulação de Arquivos e JSON
while 0 < opcao < 4:
if opcao == 1:
resp = "S"
while resp == "S":
inventario[input("Digite o número patrimonial: ")] = [
input("Digite a data da última atualização: "),
input("Digite a descrição: "),
input("Digite o departamento: ")]
resp = input("Digite <S> para continuar.").upper()
elif opcao == 2:
with open("inventario.csv", "a") as inv:
for chave, valor in inventario.items():
inv.write(chave + ";" + valor[0] + ";" +
valor[1] + ";" + valor[2] + "\n")
print("Persistido com sucesso!")
elif opcao == 3:
with open("inventario.csv", "r") as inv:
print(inv.readlines())
Manipulação de Arquivos e JSON
opcao = int(input("Digite: "
"\n<1> para registrar ativo"
"\n<2> para persistir em arquivo"
"\n<3> para exibir ativos armazenados: "))

Vejamos alguns pontos importantes para serem abordados:


• Criamos um dicionário de dados, chamado “inventario”, e montamos um menu de
escolha, com as opções 1, 2 ou 3. Enquanto o usuário digitar qualquer um dos três valores,
o programa continuará sendo executado, entretanto, para qualquer outro valor, o
programa será encerrado. Se o valor digitado for “1”, iremos colocar o usuário em outro
laço “while” e, enquanto ele digitar “S”, será permitido a ele adicionar itens para o nosso
dicionário “inventario”.
• Se o valor digitado for “2”, abriremos o arquivo “inventario.csv” em modo de
concatenação e, então, para cada objeto encontrado no nosso dicionário, iremos adicionar
um linha no arquivo. Na linha, escreveremos a chave e os valores desta chave separados
por “;” (para o Excel, isso indicará que cada valor deverá ficar em uma coluna). Ao término
da linha, adicionamos uma quebra de linha “\n”, isso também indicará ao Excel uma
quebra de linha, indicando que temos, na sequência, outro objeto.
Manipulação de Arquivos e JSON
Se finalmente o valor digitado for “3”, então, abriremos o arquivo em modo
de leitura e utilizaremos o método “readlines()” para exibirmos todo o
conteúdo do arquivo.
Após a execução do seu projeto e a verificação de que esteja tudo ok, abra
dentro do próprio PyCharm o seu arquivo “csv”, assim como fizemos com o arquivo
“txt”, e observe que talvez, dependendo da sua instalação, será necessária uma
atualização no seu PyCharm.
Faça a instalação e reinicie o seu PyCharm para que o plugin possa estar
devidamente configurado. Instalar o plugin é importante para que você possa
explorar todos os recursos adicionais que a IDE poderá lhe oferecer para a
manipulação de arquivos “CSV”, nesse caso. Essa atualização pode ser necessária
para outros conteúdos que veremos no decorrer do curso. Sempre que puder,
realize-as para que tenha uma IDE com o máximo de recursos possíveis.
Procure abrir o seu arquivo no Excel, caso o tenha instalado em seu
computador, você verá que os itens estarão devidamente separados e que você
poderá manipulá-los, ordená-los e realizar qualquer outra operação necessária com
os dados que foram persistidos no arquivo CSV
Manipulação de Arquivos e JSON
Perceba que o nosso código ficou um pouco extenso, e oferecemos poucas
funções para o usuário. Isso significa que seria interessante, para esses exemplos,
aplicarmos o conceito das funções e da modularização. Por isso, vamos criar as
funções que simplificariam esse código.
Seguiremos aprimorando nossa estrutura de projeto e, em vez de criarmos
simplesmente um arquivo com as funções, vamos criar um “Python Package”
chamado “Funcoes” e, dentro desse pacote, iremos criar todos os nossos arquivos
que armazenarão funções. Começaremos criando o arquivo “Funcoes_Arquivos.py”,
aproveite também para arrastar o arquivo “Funcoes.py” que estava dentro do pacote
“3_2_Dicionarios” para o nosso pacote “Funcoes”

Renomeie o arquivo “Funcoes.py” para “Funcoes_Dicionarios.py”, somente a


fim de identificar sua origem. Para renomear, clique com o botão direito sobre o arquivo,
escolha a opção “Refactor” e, em seguida, “Rename”. Agora, atualize o
arquivo “ManagerUsers.py”, que está no pacote “3_2_Dicionarios”.
Pronto, dessa forma, todos os nossos arquivos que armazenarem funções
estarão localizados em um mesmo pacote, o que nos facilitará reaproveitar funções
entre projetos diferentes e também padronizar as importações.
Manipulação de Arquivos e JSON
Pronto, dessa forma, todos os nossos arquivos que armazenarem funções
estarão localizados em um mesmo pacote, o que nos facilitará reaproveitar funções
entre projetos diferentes e também padronizar as importações.

def chamarMenu():
escolha = int(input("Digite: "
"\n<1> para registrar ativo"
"\n<2> para persistir em arquivo"
"\n<3> para exibir ativos armazenados: "))
return escolha
def registrar(dicionario):
resp="S"
while resp=="S":
dicionario[input("Digite o número patrimonial: ")]=[
input("Digite a data da última atualização: "),
input("Digite a descrição: "),
input("Digite o departamento: ")]
resp=input("Digite <S> para continuar.").upper()
Manipulação de Arquivos e JSON
def persistir(dicionario):
with open("inventario.csv", "a") as inv:
for chave, valor in dicionario.items():
inv.write(chave + ";" + valor[0] + ";" +
valor[1] + ";" +valor[2]+"\n")
return "Persistido com sucesso"
def exibir():
with open("inventario.csv", "r") as inv:
linhas=inv.readlines()
return linhas

Foram criadas, no código apresentado, quatro funções:


• A função chamarMenu() apenas exibe para o usuário as opções que ele
possui para a manipulação do inventário e retorna o valor selecionado por
meio da variável “escolha”;
• A função registrar() irá receber o dicionário responsável por armazenar os
ativos e, então, irá preenchê-lo, enquanto o usuário digitar “S”;
Manipulação de Arquivos e JSON
A função persistir() ficou encarregada de descarregar o dicionário que for
passado como parâmetro para dentro do arquivo “inventario.csv”; e
• A função exibir() irá, finalmente, retornar o conteúdo das linhas do arquivo
“inventario.csv” por meio da variável “linhas”.
Agora, vamos criar o arquivo “Inventario2.py”, com o seguinte
código:
from Capitulo5.Funcoes.Funcoes_Arquivos import *
inventario={}
opcao=chamarMenu()
while 0 < opcao < 4:
if opcao==1:
registrar(inventario)
elif opcao==2:
persistir(inventario)
elif opcao==3:
print(exibir())
opcao = chamarMenu()
Manipulação de Arquivos e JSON
O código do nosso arquivo “Inventario.py” tornou muito mais simples e muito
mais fácil aplicar alterações e/ou manutenções. Uma atenção para a linha na qual
chamamos o método exibir(), pois o chamamos dentro de um print() que será
responsável por exibir tudo o que método exibir() retornar.
Repare, também, algo interessante. O arquivo “inventario.csv” é utilizado
dentro das funções que estão no arquivo Funcoes_Arquivo.py, que, por sua vez,
está no pacote “Funcoes”, já o arquivo “inventario.csv” está no pacote
“3_3_ManipulaArquivos”, ou seja, estão em pacotes diferentes. Mesmo assim, as
funções reconhecem o arquivo “inventario.csv”.
Agora, repare onde será fundamental o programador Python... A saída dos
dados do “inventario.csv”, pelo Python, está clara? Se tivermos 200 ativos
cadastrados, imagine como ficaria a saída! Uma bagunça, não é mesmo? E se
quiséssemos saber, por exemplo, quais as descrições dos ativos que pertencerem a
um departamento, em específico? Ou, ainda, quais os ativos que foram atualizados
hoje? Agora, caberá a você recuperar esses dados e trabalhá-los da melhor forma
possível, trazendo inteligência para o seu gerenciamento do ambiente. Será
fundamental, neste momento, a manipulação de Strings, e é com esse assunto que
iremos trabalhar no próximo tópico.
Manipulação de Arquivos e JSON
Manipulação de Strings na recuperação dos dados de arquivos
No tópico anterior, paramos com a missão de melhorarmos a recuperação
dos dados de um arquivo. Atualmente, o nosso arquivo “Inventario.py” retorna todas
as informações do arquivo “inventario.csv” de uma forma nada agradável, por
exemplo, para que se possa apresentar em uma reunião. Começaremos pelo
seguinte: o número patrimonial do ativo, normalmente, não é um dado importante
para ser exibido, salvo em consultas específicas.
É como se eu fosse até o supermercado e comprasse um refrigerante, mas,
antes, quisesse saber o código que representa o refrigerante no estoque do
supermercado... Insano, não é mesmo? Imagine-se, agora, fazendo as compras do
mês e querendo saber todos os códigos de todos os produtos, ou seja, temos um
dado (código do produto), para essa situação específica, que não agrega
absolutamente nada, tornando-se um dado descartável para a situação.
O mesmo podemos pensar sobre o número do patrimônio, que, para um
relatório simples, não se faz necessário. A nossa função exibir() retorna todos os
elementos dos ativos em forma de lista, e cada elemento da lista é um ativo que
possui: número patrimonial, data da última alteração, descrição e departamento,
todos separados por “;”. Teremos que tratar cada linha (ativo) do nosso arquivo.
Manipulação de Arquivos e JSON
Slice de String
Vejamos como poderíamos retirar esse código durante a exibição simples dos
ativos. Para o nosso caso, vamos alterar o nosso arquivo “Inventario.py”, conforme
demonstrado a seguir:

from Capitulo5.Funcoes.Funcoes_Arquivos import *


inventario = {}
opcao = chamarMenu()
while 0 < opcao < 4:
if opcao == 1:
registrar(inventario)
elif opcao == 2:
persistir(inventario)
elif opcao == 3:
resultado = exibir()
for linha in resultado:
print(linha[2:-1])
opcao = chamarMenu()
Manipulação de Arquivos e JSON
• Primeiro, atribuímos para a variável “resultado” os dados que forem
retornados pela função exibir(), ou seja, o conteúdo do arquivo
“inventario.csv” em forma de lista.
• Montamos um “for” para percorrer toda a lista, isso porque não queremos
que saia o número do patrimônio em todos os ativos.
De cada linha, iremos exibir somente do terceiro caractere [2] até o último
[-1]. Repare que fizemos esse recorte no elemento da lista por meio do
recurso “[2:-1]”, que se chama “slice” e representa um recorte em uma
String. Cada elemento da lista é uma string, e, por isso, podemos fatiá-la e
exibir somente o que desejamos. Toda string tem, para o seu primeiro
caractere, a posição 0, logo, estamos descartando a posição 0 (número do
patrimônio) e a posição 1 (o “;”), exibindo do caractere 2 (primeiro dígito da
data da última atualização) até o final, que é representado pelo -1.

O recurso “slice” facilita muito a manipulação de Strings, mas devemos tomar


muito cuidado, pois, às vezes, a solução não é tão simples.
Manipulação de Arquivos e JSON
Na verdade, não é essa a lógica correta, o necessário é que ele retorne do primeiro
caractere, após o primeiro “;” encontrado, até o final da string. Para isso, precisaremos
localizar o “;”, ou seja, a sua posição dentro da string, e é aí que entra o método find().

Método find() e o poderoso método split()


O método find(), também utilizado por Strings, permite que você encontre um
caractere e/ou uma parte da string (conjunto de caracteres), retornando a posição da
primeira incidência encontrada. Por exemplo: caso tenhamos a string “AmoPython” e
executarmos um comando como: “AmoPython”.find(“o”), ele irá retornar o valor 2,
pois a primeira vogal “o” se encontra na posição 2. Lembre-se de que a String
começa do elemento zero. E caso ele não encontre o caractere desejado, irá
retornar o valor “-1”. Agora, o nosso código do arquivo “Inventario.py” deverá ficar da
seguinte forma:

from Funcoes.Funcoes_Arquivos import *


inventario={}
opcao=chamarMenu()
Manipulação de Arquivos e JSON
from Capitulo5.Funcoes.Funcoes_Arquivos import *
inventario = {}
opcao = chamarMenu()
while 0 < opcao < 4:
if opcao == 1:
registrar(inventario)
elif opcao == 2:
persistir(inventario)
elif opcao == 3:
resultado = exibir()
for linha in resultado:
print(linha[linha.find(";") + 1:-1])
opcao = chamarMenu()

O que está na cor vermelha, no código apresentado, representa a única


alteração que fizemos. Substituímos o número “2” pela implementação do método
find(), ele irá retornar a posição do primeiro “;” encontrado e, então, acrescentará +1
para que não exiba o próprio “;” na saída. Agora, se tivermos, em nosso arquivo
“inventario.csv”.
Manipulação de Arquivos e JSON
for linha in resultado:
separacao=linha[linha.find(";")+1:-1]
data=separacao[0:separacao.find(";")]
separacao = separacao[separacao.find(";")+1:-1]
descricao=separacao[0:separacao.find(";")]
departamento=linha[linha.rfind(";")+1:-1]
print("Data.........: ", data)
print("Descrição....: ", descricao)
print("Departamento.: ", departamento)
opcao = chamarMenu()

Incluir o trecho abaixo para separar apenas a data

data = separacao[0:separacao.find(";")]

Incluir o trecho abaixo para descartar a data

separacao = separacao[separacao.find(";")+1:-1]
Manipulação de Arquivos e JSON
descricao=separacao[0:separacao.find(";")]

e Agora o Departamento:
departamento=linha[linha.rfind(";")+1:-1]

Finalmente, conseguimos fazer a devida separação e, então, exibirmos por


meio dos prints, conforme o código apresenta. A saída ficou bem melhor agora, não
é mesmo? e Agora imagine se tivéssemos 40 dados em vez? No Python temos o método
split(), nosso verdadeiro herói! Ele quebra uma String
de acordo com um conjunto de caracteres que você pode definir. Se olharmos o
conteúdo da nossa variável “linha”, perceberemos que os nossos dados são
separados por um “;” (daí a importância em não separar os dados com um símbolo
comum qualquer, procure sempre utilizar símbolos que dificilmente existirão dentro
de uma String, como: #, !, ##, entre outros). A função split() irá gerar uma lista, e, em
cada posição, teremos uma parte da String, de acordo com a quebra que foi
proposta. Por exemplo:
Manipulação de Arquivos e JSON
lista=”AmoPython”.split(“o”) => teremos uma lista com três posições: na
primeira posição, teremos “Am”; na segunda, teremos “Pyth”; e, na terceira, “n”, uma
vez que quebramos a String por meio da vogal “o”. Essa função facilitará muito o
nosso trabalho, observe como o código ficará agora:
for linha in resultado:
lista=linha.split(";")
print("Data.........: ", lista[1])
print("Descrição....: ", lista[2])
print("Departamento.: ", lista[3])
opcao = chamarMenu()

Compare com a solução anterior e veja o quão simples foi essa solução
proposta. Apesar de as duas funcionarem e retornarem as informações desejadas, a
segunda proposta, com o método split(), é muito mais prática e rápida de ser
implementada. Sempre que manipular Strings, terá várias formas de chegar ao mesmo
resultado, mas, quando achar que o seu código está muito extenso e
repetitivo, procure saber se não existe algum método capaz de simplificar o que
você deseja realizar.
Manipulação de Arquivos e JSON
Manipulando arquivos de terceiros
Até o momento, manipulamos dados e arquivos que nós mesmos
organizamos e criamos e, sem dúvida, esse é o mundo perfeito. Entretanto, em
muitas ocasiões, você deverá realizar a leitura e recuperar dados de arquivos de
terceiros, como, por exemplo, logs gerados pelo sistema operacional, arquivos de
configuração de roteadores e outros equipamentos ou ainda arquivos gerados por
ferramentas de outros programadores. Por isso, nesse tópico, realizaremos o tratamento
dos dados de um arquivo de terceiro, a fim de praticarmos e fixarmos os métodos, sobre
Strings e arquivos, abordados até o momento e também para que possamos praticar um
pouco mais a lógica para o trabalho com arquivos. Vamos lá.
Comece acessando o link: https://data.boston.gov/dataset/economic�indicators-legacy-
portal, que irá direcioná-lo para uma página que permitirá realizar o
download de um arquivo “csv”, que contém indicadores oficiais relacionados à
economia da cidade de Boston-EUA.
Após baixar o arquivo, arraste-o para dentro do pacote 3_3_ManipulaArquivos
e crie o arquivo Boston.py. Abra o arquivo “economic-indicators.csv” e você irá
encontrar, na primeira linha, as siglas dos indicadores e, nas linhas subsequentes,
os dados separados por vírgula, seguindo a ordem dos indicadores.
Manipulação de Arquivos e JSON
Para facilitar
nossa análise, seguem, a seguir, os significados das siglas, encontradas na primeira
linha do arquivo, que utilizaremos para o nosso exemplo:
• Year = ano do dado
• Month = mês do dado
• logan_passengers = quantidade de passageiros, internacionais e
domésticos, que passaram pelo aeroporto de Logan.
• logan_intl_flights = total de voos internacionais que partiram do aeroporto
de Logan.
• hotel_occup_rate = porcentagem de vagas ocupadas nos hotéis de
Boston.
• hotel_avg_daily_rate = média da diária, em dólar, de um hotel em Boston.
• total_jobs,unemp_rate = porcentagem de desempregados em Boston.

Deveremos buscar as respostas às seguintes questões:


- Qual o total de voos internacionais que partiram do aeroporto de Logan no
ano de 2014?
- Quando (mês/ano) ocorreu o maior trânsito de passageiros no aeroporto de
Logan?
Manipulação de Arquivos e JSON
- Qual o total de passageiros que passaram pelo aeroporto de Logan, no ano
que for especificado pelo usuário?
- Qual o mês que possui a maior média da diária de um hotel, com base no
ano especificado pelo usuário?
Para responder a essas perguntas, deveremos montar nossa ferramenta. Por
isso, no arquivo “Boston.py”, digite o código seguinte para resolver a primeira
questão:
with open("economic-indicators.csv","r") as boston:
total=0
for linha in boston.readlines()[1:-1]:
total=total+float(linha.split(",")[3])
print("O total de voos é: ", total)
Detalhando um pouco o código apresentado:
• Na primeira linha, abrimos o arquivo em modo somente de leitura;
• Criamos uma variável para armazenar o total de voos;
• Montamos um laço “foreach” para percorrermos somente da linha um “1”
até a última linha válida, descartando a linha zero “0” (em que temos
apenas os títulos);
Manipulação de Arquivos e JSON
Atribuímos, na variável total, o valor do terceiro elemento da lista que foi
criada por meio do split(), separando os elementos por vírgula(“,”);
• Imprimimos o conteúdo da variável, quando o laço for encerrado e a
variável “total” tiver acumulado todos os valores do arquivo.
Agora, complemente o arquivo resolvendo as outras questões, procure
resolver uma a uma e siga abaixo para ver a solução proposta para a versão final do
nosso arquivo “Boston.py”.
with open("economic-indicators.csv","r") as boston:
total_voos=0
maior=0
total_passageiros=0
maior_media_diaria=0
ano_usuario = input("Qual ano deseja pesquisar? ")
for linha in boston.readlines()[1:-1]:
lista=linha.split(",")
total_voos=total_voos+float(lista[3])
Manipulação de Arquivos e JSON
if float(lista[2])>float(maior):
maior=lista[2]
ano=lista[0]
mes=lista[1]
if ano_usuario==lista[0]:
total_passageiros=total_passageiros+float(lista[2])
if float(lista[5])>float(maior_media_diaria):
maior_media_diaria=lista[5]
mes_maior_diaria=lista[1]
print("O total de voos é: ", total_voos)
print("O mês/ano de maior movimento no aeroporto foi: ", str(mes),"/",str(ano))
print("O total de passageiros do ano ", ano_usuario, "foi de ", total_passageiros)
print("O mês do ano ", ano_usuario, "com maior média para diária de hotel foi ",
mes_maior_diaria)
Para a resolução das perguntas que foram realizadas anteriormente, você
pode observar, no código acima, a criação das quatro variáveis que servirão como
base para a resposta, mais uma variável que irá armazenar o ano específico que o
usuário deseja consultar.
Manipulação de Arquivos e JSON
Dentro do “foreach”, foi realizada a identificação dos dados
e as respectivas atribuições, até o seu final, em que, então, foram apresentados os
valores das variáveis nas últimas quatro linhas do código.
Agora, você mesmo pode tentar localizar algumas informações, baixar outros
arquivos “csv” e fazer o filtro que desejar, como, por exemplo, tentar localizar o mês
do ano que possui a maior taxa de ocupação das vagas nos hotéis em Boston ou
ainda em que mês/ano ocorre a menor taxa de desemprego na cidade de Boston.
Enfim, são inúmeras possibilidades, e o céu é o limite.

Um caminho para a portabilidade


Já trabalhamos com arquivos que nós mesmos geramos e com arquivos de
terceiros, mas você também deve pensar em outros profissionais que podem
precisar realizar leitura sobre os seus arquivos, e pensando um pouco maior ainda,
os seus arquivos gerados pelo Python podem ser exportados para outras
plataformas, até mesmo por uma aplicação mobile. O que desejamos dizer é que
não basta o Python ser portátil, os dados que você gera por meio dele também
devem ter a qualidade da portabilidade.
Manipulação de Arquivos e JSON
Imagine que você irá desenvolver alguma ferramenta que deverá se
comunicar com outra aplicação, como, por exemplo, se conectar aos Correios, à
Receita Federal, ao Detran ou, simplesmente, à aplicação de um programador que
fala outro idioma em outro país... Como será possível estabelecer uma comunicação
entre a sua aplicação e qualquer outra aplicação do mundo que queira trocar dados?
Simples: utilizando um padrão de comunicação.
Um padrão muito comum utilizado pelos programadores é o XML, que permite
a troca de dados entre plataformas distintas.
Uma prova disso é a nota fiscal eletrônica, que roda em todo o País e não importa se você
usa Windows 32 bits, 64 bits, Linux, iOS, Solaris ou qualquer outro sistema operacional,
tampouco importa a
linguagem que foi utilizada para desenvolver a ferramenta e não importa também se
o programa que irá gerar a nota fiscal for realizado em .Net, Java, PHP, Python ou
qualquer outra linguagem. O único fator que importa é que os dados sejam criados
dentro do padrão XML. Mas não abordaremos o XML, que é mais comumente
utilizado para sistemas comerciais, como é o caso da nota fiscal eletrônica.
Abordaremos outro padrão, também muito utilizado, para que você garanta
que a saída dos dados da sua aplicação tenha portabilidade, esse é o tal JSON!
Manipulação de Arquivos e JSON
I
Manipulação de Arquivos e JSON
JSON é uma sigla, JavaScript Object Notation, que representa um padrão
para armazenamento de dados, cuja principal função é permitir a troca de dados
entre aplicações e plataformas distintas. O Python possui um módulo para facilitar o
trabalho com esse tipo de padronização. Vamos a um exemplo prático, crie um
arquivo chamado “Manipular_JSON.py” e digite o código a seguir:
import json
inventario={}
opcao=int(input("Digite: "
"\n<1> para registrar ativo"
"\n<2> para exibir ativos armazenados: "))
while opcao>0 and opcao<3:
if opcao==1:
resp = "S"
while resp == "S":
inventario[input("Digite o número patrimonial: ")] = [
input("Digite a data da última atualização: "),
input("Digite a descrição: "),
input("Digite o departamento: ")]
Manipulação de Arquivos e JSON
resp = input("Digite <S> para continuar.").upper()
with open("inventario_json.json", "w") as arq_json:
json.dump(inventario, arq_json)
print("JSON gerado!!!!")
resp = input("Digite <S> para continuar.").upper()
with open("inventario_json.json", "w") as arq_json:
json.dump(inventario, arq_json)
print("JSON gerado!!!!")
elif opcao==2:
with open("inventario_json.json", "r") as arq_json:
resultado = json.load(arq_json)
for chave, dado in resultado.items():
print("Data.........: ", dado[0])
print("Descrição....: ", dado[1])
print("Departamento.: ", dado[2])
opcao = int(input("Digite: "
"\n<1> para registrar ativo"
"\n<2> para exibir ativos armazenados: "))
Manipulação de Arquivos e JSON
Como você já percebeu, o exemplo adotado foi o mesmo do tópico anterior,
para que você possa ter um parâmetro entre o código que manipula um arquivo “txt”,
“csv” ou “html” e o código que utiliza o padrão JSON.
O primeiro detalhe a ser observado está na primeira linha do código, o
“import”. Como já afirmamos anteriormente, o Python possui um módulo para a
manipulação de JSON e, para que possamos utilizar os seus objetos e métodos,
devemos importá-lo.
Perceba que, nesse exemplo, retiramos a antiga opção “2”, que era
responsável por persistir no arquivo, pois agora realizamos a persistência logo após
o usuário digitar todos os dados no dicionário “inventario”, assim que o loop for
encerrado, já realizamos a persistência no formato JSON.
Para gravarmos o dicionário “inventario” no arquivo, utilizamos o método
dump(), que pertence ao objeto “json”. Esse método é formado, basicamente, por
dois parâmetros: o que será gravado, no nosso caso, o dicionário “inventario” e onde
será gravado, quando definimos por meio do alias “arq_json”, que aponta para o
arquivo “inventario_json.json”, o qual estará aberto em modo escrito, ou seja, caso
ele não exista será criado automaticamente e, caso já exista, será sobrescrito.
Manipulação de Arquivos e JSON
Por que o arquivo não foi aberto para concatenação, assim como fizemos no
tópico anterior? Porque, quando o método dump() fosse chamado, após a
primeira vez, ele não iria adicionar as informações do dicionário “inventario” ao
arquivo, mas criar uma nova estrutura dentro do arquivo.

Execute e lance dois ativos no inventário, depois disso, encerre sua aplicação
e veja que surgiu o arquivo “inventario_json.json”.
E, então, reconheceu algo na estrutura do arquivo? Parece com alguma
estrutura de dados que vimos dentro do Python? Sim, isso mesmo! É o dicionário de
dados, isso significa que a estrutura do JSON não o assusta, pois já manipulamos
bastante a estrutura de dicionário de dados por meio da chave e dos dados.
Continuando a explicação do código, na opção “2”, abrimos o nosso arquivo
em modo de leitura apenas e, então, chamamos o método load(), que também
pertence ao objeto “json”. Ele descarrega o arquivo informado no parâmetro para
uma variável, no nosso exemplo, a variável “resultado”. Em seguida, montamos um
laço “foreach”, que irá trazer a chave (número patrimonial) e os dados (uma lista com
data, descrição e departamento); finalizamos com a exibição e o menu de opções
novamente.
Manipulação de Arquivos e JSON
Agora perceba que, como não utilizamos, na opção “1”, o modo de
concatenação, se você executar novamente o seu código, verá que o seu arquivo
anterior será sobrescrito, isto é, se você lançar um ativo, o seu arquivo ficará apenas
com um ativo e não mais com três (considerando os outros dois que você preencheu
anteriormente). Para solucionar isso, faremos uma alteração na estrutura do nosso
código, ao invés de criarmos o dicionário “inventario” vazio, já o criaremos
preenchido pelo arquivo, assim, a nossa opção “1” irá adicionar mais um objeto ao
dicionário, que já estará preenchido com o conteúdo do arquivo e, finalmente,
quando for realizar a gravação, irá gravar todos os objetos que estiverem no
dicionário. Veja como ficará o código:
import json
with open("inventario_json.json", "r") as arq_json:
inventario = json.load(arq_json)
opcao=int(input("Digite: \n<1> para registrar ativo"
"\n<2> para exibir ativos armazenados: "))
while opcao>0 and opcao<3:
if opcao==1:
resp = "S"
Manipulação de Arquivos e JSON
while resp == "S":
inventario[input("Digite o número patrimonial: ")] = [
input("Digite a data da última atualização: "),
input("Digite a descrição: "),
input("Digite o departamento: ")]
resp = input("Digite <S> para continuar.").upper()
with open("inventario_json.json", "w") as arq_json:
json.dump(inventario, arq_json)
print("JSON gerado!!!!")
elif opcao==2:
for chave, dado in inventario.items():
print("Data.........: ", dado[0])
print("Descrição....: ", dado[1])
print("Departamento.: ", dado[2])
opcao = int(input("Digite: "
"\n<1> para registrar ativo"
"\n<2> para exibir ativos armazenados: "))
Manipulação de Arquivos e JSON
As alterações estão destacadas pela cor vermelha. Criamos o nosso dicionário
“inventario”, já o preenchendo com o conteúdo do arquivo “inventario_json.json”. Na
opção “2”, de exibição, basta utilizarmos o dicionário “inventario” no “foreach”, assim
percorreremos todos os dados de maneira atualizada.
Mas, agora, vamos para um pequeno problema. Elimine o arquivo “inventario_json.json”,
para isso, clique com o botão direito sobre o arquivo, escolha a opção “Delete”, clique no
botão “OK” e, no painel debaixo do PyCharm,normalmente irá aparecer um botão com o
texto “Do Factor”, clique sobre ele para confirmar a exclusão. Rode novamente a aplicação
e, então, verá um erro que ocorrerá porque o Python não localizou o arquivo para
preencher o dicionário “inventario”.
Uma forma simples para resolver esse problema é identificar se o arquivo já
existe. Para isso, precisaremos importar o pacote “os” (Operation System), que
permite acessar objetos e funções referentes ao sistema operacional. Uma dessas
funções é a “path.exists()”, que retorna “True”, caso encontre o arquivo especificado
como parâmetro, ou “False”, se o arquivo não for encontrado. Por isso, nossa
alteração será realizada somente no início do código, conforme podemos observar
na sequência a seguir:
Manipulação de Arquivos e JSON
import json
import os
if os.path.exists("inventario_json.json"):
with open("inventario_json.json", "r") as arq_json:
inventario = json.load(arq_json)
else:
inventario={}
opcao=int(input("Digite: \n<1> para registrar ativo"
"\n<2> para exibir ativos armazenados: "))

Observe, nas linhas que estão na cor vermelha, que colocamos uma condição
para a criação ou preenchimento do dicionário “inventario”, que é: se o arquivo
existir, então, preencha o dicionário com o conteúdo do arquivo, caso contrário (se o
arquivo não existir), crie o dicionário “inventario” vazio. Pronto!
Pronto? Podemos melhorar um último detalhe, que é o fato de modularizar,
isso significa aplicar as funções. Vamos lá! Crie, no pacote “Funcoes”, o arquivo
“Funcoes_JSON.py” e digite o código seguinte:
Manipulação de Arquivos e JSON
import json
import os
def chamarMenu():
escolha = int(input("Digite: "
"\n<1> para registrar ativo"
"\n<2> para exibir ativos armazenados: "))
return escolha
def ler_arquivo(arquivo):
if os.path.exists(arquivo):
with open(arquivo, "r") as arq_json:
dicionario=json.load(arq_json)
else:
dicionario = {}
return dicionario
def gravar_arquivo(dicionario,arquivo):
with open(arquivo, "w") as arq_json:
json.dump(dicionario, arq_json)
Manipulação de Arquivos e JSON
def registrar(dicionario, arquivo):
resp = "S"
while resp == "S":
dicionario[input("Digite o número patrimonial: ")] = [
input("Digite a data da última atualização: "),
input("Digite a descrição: "), input("Digite o departamento:
")]
resp = input("Digite <S> para continuar.").upper()
gravar_arquivo(dicionario,arquivo)
return "JSON gerado!!!!"
def exibir(arquivo):
dicionario = ler_arquivo(arquivo)
for chave, dado in dicionario.items():
print("Data.........: ", dado[0])
print("Descrição....: ", dado[1])
print("Departamento.: ", dado[2])
Manipulação de Arquivos e JSON
Nesse arquivo, criamos algumas rotinas tão abstratas que poderiam funcionar
com qualquer aplicação que tivesse a função de manipular arquivos JSON, é o caso
das funções: ler_arquivo() e gravar_arquivo(). Para qualquer situação envolvendo
arquivos JSON, elas podem ser reaproveitadas, tanto que as próprias funções
registrar() e exibir() utilizam essas funções.
Agora sim, podemos pensar no nosso arquivo “Manipular_JSON.py”, que
ficará muito mais “clean”, conforme podemos perceber no código a seguir:
from Funcoes.Funcoes_JSON import *
inventario = ler_arquivo("inventario_json.json")
opcao=chamarMenu()
while opcao>0 and opcao<3:
if opcao==1:
print(registrar(inventario, "inventario_json.json"))
elif opcao==2:
exibir("inventario_json.json")
opcao = chamarMenu()
Manipulação de Arquivos e JSON
from Funcoes.Funcoes_JSON import *
inventario = ler_arquivo("inventario_json.json")
opcao=chamarMenu()
while opcao>0 and opcao<3:
if opcao==1:
print(registrar(inventario, "inventario_json.json"))
elif opcao==2:
exibir("inventario_json.json")
opcao = chamarMenu()

Finalizando o capítulo
Para finalizar este capítulo, você poderá aplicar todos os conceitos vistos,
desenvolvendo uma ferramenta mais completa para catalogar o inventário do seu
cliente. Armazene tudo em arquivo e crie, pelo menos, duas formas de saídas, por
modelos, atualizações e valores, por exemplo.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Nosso código agora irá alcançar voos mais altos e mais distantes. Chegou a
hora de apresentar o mundo exterior ao Python. Muitos recursos virão e as
possibilidades de aplicação aumentarão exponencialmente. Prontos para receberem
os kits de superpoderes? Vamos lá...

Utilizando pacotes externos

Seu código, até agora, teve contato apenas com recursos internos e padrões
do Python, que já existiam dentro da PVM que reina em seu computador. Comandos
e funções que compõem a linguagem, como: if, while, for, open(), split(), len(), upper(),
entre tantos outros que já abordamos, nós aprendemos a usá-los sem fazer qualquer
referência, isso porque esses comandos/funções/recursos já estão liberados para
utilização.

Obviamente, seria impossível abordar todos os pacotes externos existentes


para Python. Faremos juntos um exemplo com um pacote externo, assim, quando
precisar utilizar qualquer pacote externo, o processo de instalação e importação será
o mesmo
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Apresentamos... Geo Py – Geopy

Resumidamente, as etapas 1, 2 e 3 significam:


• No aplicativo mobile, estará a etapa 1, que terá a responsabilidade de receber o endereço, por voz
ou texto, e gerar um arquivo JSON no servidor, com o endereço que foi digitado ou falado.
• Na etapa 2, que rodará no servidor, SUA aplicação Python irá realizar a leitura do arquivo JSON
(entrada.json), que armazena o endereço e,então, deverá escrever em outro arquivo JSON
(saida.json) as coordenadas geográficas referentes ao endereço.
• Na etapa 3, outra aplicação irá consumir o arquivo “saida.json”, dentro de determinado intervalo
de tempo, e, então, irá gerar uma rota que será exibida ao portador da necessidade especial,
somente quando ele ativar o botão “Iniciar o trajeto”
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Com base na descrição das três etapas básicas, você ficou responsável por
auxiliar na segunda etapa. E então? Será que é difícil montar uma rotina em Python,
para ler um arquivo JSON, converter o endereço obtido em coordenada geográfica e
escrever as coordenadas obtidas em um outro arquivo JSON? Vamos avaliar os
verbos negritados! Ler e escrever (arquivos JSON) nós já fizemos, logo, não será o nosso
maior desafio. Converter o endereço para as coordenadas parece ser o mais
difícil, não é mesmo?
Pois é, você está enganado, a não ser que queira criar tudo do zero.
Apresentamos para você o pacote externo “Geopy”, que possui, entre outras, a função
de converter um texto em coordenadas geográficas, assim iremos conseguir ajudar o
departamento de inovação tecnológica de maneira simples e rápida. Vamos colocar
esse “superpoder” em nossa aplicação.

Instalando Geopy

Como já dissemos anteriormente, o pacote/módulo Geopy é externo, por isso,


precisaremos baixá-lo do link: https://pypi.org/project/geopy/, conforme a figura a
seguir (Salve-o em um local de fácil acesso, por exemplo: c:\pacotes.):
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Agora, abra o console do seu sistema operacional e direcione até a pasta
criada. No Windows, deverá seguir: <Windows>+<R> / cmd <enter> e, na tela de console, usar
o comando “cd” (change directory) para se deslocar entre diretórios,
conforme está sublinhado em vermelho na figura seguinte (para quem baixou o
arquivo exatamente em c:\pacotes):

pip install geopy

Caso apareça uma mensagem de erro do tipo “não é reconhecido como


comando”, significa que você não tem o comando “pip” instalado/configurado. Esse é
o comando responsável por instalar pacotes externos no seu Python. Você deve
utilizar:

• pip install <nomeDoPacote> => para instalar ou


• pip uninstall <nomeDoPacote> => para desinstalar o pacote especificado.
Se você precisar instalá-lo, digite no console o seguinte comando:
• python -m ensurepip --upgrade
Caso o comando “python” não funcione, é porque você se esqueceu de marcar
a opção “Add to path” no momento da instalação do Python. Recomendamos que volte
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Depois, volte a digitar:
• pip install geopy

Usando Geopy
Agora que o pacote está devidamente instalado, vamos montar o nosso código.
Para isso, abra o nosso projeto no PyCharm, crie um novo “Python Package”,
chamado: “5_1_Wazeyes”, dentro dele, crie um arquivo “Python File”, chamado
“Converter_geolocalizacao.py” e digite o seguinte código:

from geopy.geocoders import Nominatim


geolocator = Nominatim(user_agent="wazeyes") # Nome do seu aplicativo
location = geolocator.geocode("175 5th Avenue NYC")
print(location.address)
print((location.latitude, location.longitude))

o
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Com as linhas, já conseguimos a parte do código que deveria ser a mais difícil,
isto é, capturamos uma string que representa um endereço e convertemos para as
coordenadas geográficas latitude e longitude, para que possam ser aplicadas, por
outra aplicação, sobre um mapa. Agora, a missão é criar um arquivo JSON com um
endereço, consumi-lo, gerar as coordenadas e gravar em outro arquivo JSON. Nesse
momento, antes de seguir a leitura da sequência do código a seguir, aproveite para
treinar, crie o arquivo JSON (conforme a figura seguinte) e produza o código que irá
ler o arquivo do endereço e gerar outro arquivo com as coordenadas, vamos lá!

{ "endereco": ["Lins de Vasconcelos", "1222", "Aclimacao", "Sao Paulo", "SP"]}

from geopy.geocoders import Nominatim


from Funcoes.Funcoes_JSON import ler_arquivo,gravar_arquivo
geolocator = Nominatim(user_agent="wazeyes")
dicionario=ler_arquivo("entrada.json")
lista=dicionario["endereco"]
endereco=lista[0] + "," + lista[1] + " " + lista[2] + " " + lista[3]
location = geolocator.geocode(endereco)
saida={"coordenadas": (location.latitude, location.longitude)}
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

E. então, havia pensando em utilizar as funções (ler_arquivo() e


gravar_arquivo()) que criamos anteriormente no arquivo Funcoes_JSON? Espero que
sim... Essa é a mágica em criarmos módulos flexíveis a ponto de serem
reaproveitados em qualquer outro projeto, ou ao menos na maioria dos projetos.
Detalhando um pouco mais o código apresentado: temos duas importações
(Geopy e do arquivo no qual encontramos as funções que desejamos e que já
havíamos criado), capturamos o conteúdo do ler_arquivo() em um dicionário,
recuperamos somente a lista, com base na lista, montamos o conteúdo da variável
“endereco” por meio da concatenação dos itens da lista e obtivemos uma variável do
tipo string, criamos um dicionário chamado “saida” para armazenar a chave
“coordenadas” e, dentro dela, o resultado do método geocode() sobre a nossa variável
“endereço”, ou seja, as coordenadas e, por fim, gravamos o arquivo “saida.json” com
o dicionário “saida”. Um show de conceitos, não é mesmo?

o
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Praticamente, em cada linha, temos um conceito e uma estrutura diferentes.
Por isso, é muito importante que você conheça bem as estruturas de dados já
abordadas. Se ainda você se sentir desconfortável em utilizar qualquer uma das
estruturas, não deixe para depois. Pratique mais (não é decorar – é praticar), refaça
exercícios, procure aplicações no seu cotidiano, mesmo que sejam bem simples e que
você nem chegue a implementá-las posteriormente, mas não deixe de praticar até
dominar as estruturas básicas que o Python disponibiliza.

Um pouco mais sobre o Geopy


Podemos, ainda, utilizar o Geopy para obter mais informações com base em
um endereço fornecido. Crie um arquivo chamado “Geolocalizacao_plus.py” e digite o
seguinte código:
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="wazeyes")
endereco=input("Digite um endereco com número e cidade. "
"\nExemplo: avenida paulista, 100 São Paulo:\n")
resultado = str(geolocator.geocode(endereco)).split(",")
if resultado[0]!='None':
print("Endereço completo.: ", resultado)
print("Bairro............: ", resultado[1])
print("Cidade............: ", resultado[2])
print("Regiao............: ", resultado[3])

Vamos analisar esse código:


• Importamos o nosso pacote Geopy e, em seguida, solicitamos ao nosso
usuário o endereço que ele deseja pesquisar.
• Atribuímos, para a nossa lista “resultado”, o resultado obtido pela execução
do método geocode() junto ao endereço digitado pelo usuário. O que esse
método faz exatamente? Ele pesquisa a string recebida (no nosso caso, o
conteúdo da variável “endereco”) dentro do GoogleMaps e retorna em forma
de string, com vários elementos separados por “vírgula”. Por isso, dividimos
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Verificamos se o endereço é um endereço válido por meio da primeira


posição da lista, que se for diferente de “None”, significa que foi encontrado
algum endereço..
• Se o endereço for válido, então, mostraremos o endereço completo, ou seja,
mesmo que você tenha digitado “Avenida Paulista, 10”, você verá CEP,
bairro, cidade e país. Logo após, mostrará apenas o bairro do endereço
localizado, seguido da cidade e da região, somente a fim de demonstrar como podemos extrair
apenas uma informação específica do endereço,
caso seja necessário.
Faça algumas experiências, experimente digitar somente um CEP, um
endereço menos completo, outro mais completo e aprenda com o comportamento do
pacote “Geopy”. Podemos também fazer o inverso, monte um novo arquivo, chamado
“Geolocalizacao_reversa.py”, com o seguinte código:
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

from geopy.geocoders import Nominatim


geolocator = Nominatim(user_agent="wazeyes")
latitude=float(input("Digite a latitude...: "))
longitude=float(input("Digite a longitude.: "))
resultado = str(geolocator.reverse(f"{latitude}, {longitude}")).split(",")
if resultado[0]!='None':
print("Endereço completo.: ", resultado)
print("Dado 1............: ", resultado[0])
print("Dado 2............: ", resultado[1])
print("Dado 3............: ", resultado[2])

Perceba, agora, que não estamos solicitando o endereço e, sim, a latitude e


longitude. O método utilizado na quarta linha não é mais o geocode() e, sim, o reverse
(), que recebe dois valores: latitude e longitude, respectivamente, e retorna o endereço
encontrado. Utilize como teste as coordenadas:
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

• Latitude: -23.5740406
• Longitude: -46.623408900000015
Logo obterá o endereço completo, e mais três dados exibidos separadamente.
Observe que, por meio de uma necessidade real, na aplicação “Wazeyes”,
tivemos a oportunidade de aprender muito sobre geolocalização e, melhor que isso,
percebemos que muitos códigos estão prontos, é só conhecer, pesquisar sobre o
pacote externo e aplicar os conhecimentos adquiridos sobre os conceitos
apresentados anteriormente. O que isso tem a ver com Defesa Cibernética? Se ainda
não caiu a ficha, vou lhe dar uma ajudazinha...

O próprio “Wazeyes” estará na forma de aplicativo e se comunicando com a


internet... seguro, isso? Você sabe que não! Caberá a você observar todo o trâmite
dos dados e as trocas dos pacotes para que possa garantir que o público-alvo não seja vítima
de ciberataques. E, se não quiser falar de aplicativos para a saúde, já
pensou em um aplicativo bancário que, por meio das coordenadas geográficas, pode
auxiliar a classificação quanto à veracidade de uma transação bancária? E para todas
as IoTs que temos no mercado, consegue perceber a gama de aplicações?
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Todos os dias úteis, você termina realizando um caminho, um tanto quanto


parecido (exceção a alguns cargos e/ou profissões que exigem viagens mundo afora).
Poderíamos delimitar uma faixa nesse mapa, como se fosse uma cerca mesmo, e,
caso saíssemos dessa faixa, o aplicativo poderia interpretar como um momento de
perigo, um sequestro-relâmpago, por exemplo. E, então, poderia avisar alguns
contatos predefinidos, por SMS ou qualquer outra aplicação para a troca de
mensagens.
Enfim, são apenas ideias relacionadas à geolocalização. Imagine quantos
pacotes externos existem e quanto espaço você tem para criar soluções, corrigir e
propor inovações. E, quanto mais “poderes” você for adquirindo, mais “$uper-herói”
você será... E então? Grande o desafio, não é mesmo? Estamos juntos nessa! Vamos
avançar para adquirir mais poderes ainda... Que venha o sistema operacional! •
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Conversando com o sistema operacional


Iremos abordar, agora, o sistema operacional e como ele pode ser um forte
aliado para os desenvolvedores de Python. Como o sistema operacional controla o
equipamento, ele é alvo preferido dos cibercriminosos e também o responsável por
nos fornecer informações muito importantes sobre o seu comportamento.
Apresentaremos, agora, um primeiro contato e você verá que é bem simples
manipular algumas informações do sistema operacional. Crie um novo “Python
Package”, chamado “5_2_SistemaOperacional”, e, nele, um novo “Python File”,
denominado “RecuperandoDados.py”, em seguida, digite o código a seguir:

import platform
print("Distribuição do Sistema Operacional.: ", platform.platform())
print("Nome do Sistema Operacional.........: ", platform.system())
print("Versão do Sistema Operacional.......: ", platform.release())
print("Arquitetura.........................: ", platform.architecture())
print("Nome do Computador..................: ", platform.node())
print("Tipo de Máquina.....................: ", platform.machine())
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Esse código aponta que precisamos importar o pacote “platform” para obtermos
informações como:
• platform(): método que retorna a distribuição exata do sistema operacional
que está sendo executado. Muito útil para que possamos desenvolver
ferramentas de inventário ou ferramentas que podem servir para apontar
computadores que não estão atualizados.
• system(): este método retorna simplesmente o sistema operacional que está
sendo executado. Isso pode auxiliar sua ferramenta a executar, por
exemplo, comandos de Windows no Windows, e comandos do Linux no
Linux, tornando-a multiplataforma
release(): retorna a versão do sistema operacional que está sendo
executada.
• architecture(): exibe a arquitetura que está em uso pela máquina.
• node(): retorna o nome do computador na rede. Mais uma vez, essa é uma
informação muito importante para o inventário. Lembra quando nós fizemos
uma ferramenta em que o usuário deveria digitar? Pois é, podemos deixar
nossas ferramentas mais independentes do usuário e, consequentemente,
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

machine(): retorna o tipo da máquina, e é muito utilizada com o método


processor(), que retorna o processador que está sendo executado, o que
pode ser muito útil, por exemplo, para providenciarmos atualizações sobre
falhas de segurança para processadores de um fabricante em específico.
Por exemplo, no ano de 2018, tivemos a divulgação das falhas de
segurança: Meltdown e Spectre, representando vulnerabilidades que
podem ser exploradas de acordo com os fabricantes de processadores,
atingindo os maiores players de mercado como: Intel, Apple e AMD. A
identificação do processador pode lhe permitir o direcionamento de patchs
de atualização para cada computador que faz parte da sua rede corporativa
python_version(): irá retornar a versão do Python que está sendo
executada. Esse método também pode ser muito importante para garantir a
plena execução da sua ferramenta, uma vez que existe uma grande
diferença entre o Python versão 2.x e o 3.x, além de diferenças menores
entre as versões intermediárias.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Temos, também, alguns outros pacotes que podem ser úteis para ações
comuns, conforme podemos observar no código a seguir, que deve ser digitado no
novo arquivo chamado “Usuario_data.py”:

import getpass
from datetime import datetime
print("Usuário.......: ", getpass.getuser())
print("Data Completa.: ", datetime.now())
print("Dia...........: ", datetime.now().day)
print("Mês...........: ", datetime.now().month)
print("Ano...........: ", datetime.now().year)
print("Hora..........: ", datetime.now().hour)
print("Minuto........: ", datetime.now().minute)
print("Segundo.......: ", datetime.now().second)
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Pandas

Pandas é uma biblioteca de código aberto que fornece estruturas de dados


fáceis de usar para a linguagem de programação Python.

• Além disso, a biblioteca fornece estrutura de dados de alto desempenho e


ferramentas de análise de dados.

• Instalação da biblioteca via PyPI:

Abra o prompt de comando do windows e execute o comando abaixo:

pip install pandas


BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Crie um arquivo pandas.py

Para utilizar a biblioteca basta realizar a importação.

import pandas

Para evitar a repetição da palavra pandas toda vez em que a biblioteca é


referenciada no código, é comum a utilização do alias pd que é uma palavra
mais curta e consequentemente reduz o tamanho das linhas de código.

# Forma mais comum de importar a biblioteca com alias


import pandas as pd

• Os exemplos de código utilizarão a importação da biblioteca com o alias pd.


BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Uma das estruturas de dados mais utilizada no pandas é o DataFrame.


Uma instância do tipo DataFrame é um objeto de duas (ou mais) dimensões
com as seguintes características:

• Suas dimensões podem ser modificadas decorrente da modificação dos


dados.
• Seus dados podem ser acessados através de rótulos ao invés de
exclusivamente por índices.
• É possível trabalhar com dados heterogênios, tanto nas linhas como
também nas colunas.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

• A classe DataFrame da biblioteca pandas possui um método construtor


com alguns parâmetros:

• data: recebe os dados no formato de lista, dicionário ou até mesmo um


DataFrame já existe.

• index: recebe uma string ou uma lista de strings que definem os rótulos das
linhas.
• columns: recebe uma string ou uma lista de strings que definem os rótulos
das colunas.
• dtype: recebe um tipo de dados com intuito de forçar a conversão do tipo
de dados do DataFrame. Por padrão esse parâmetro recebe valor None e os
tipos dos dados são inferidos.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Criando um DataFrame a partir de uma lista de tuplas:


import pandas as pd
nomes = ['Ana', 'Bruno', 'Carla']
idades = [21, 20, 22]
dados = list(zip(nomes, idades))
print(dados)
# [('Ana', 21), ('Bruno', 20), ('Carla', 22)]
df = pd.DataFrame(data = dados)
print(df)
#01
# 0 Ana 21 1
# 1 Bruno 20
# 2 Carla 22
• Note que o DataFrame cria automaticamente rótulos padrões (índices) para
que os dados sejam acessados.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Criando um DataFrame a partir de um dicionário:


import pandas as pd
dados = {'Nome': ['Ana', 'Bruno', 'Carla'], 'Idade': [21, 20, 22]}
# {'Nome': ['Ana', 'Bruno', 'Carla'], 'Idade': [21, 20, 22]}
df = pd.DataFrame(data = dados)
print(df)
# Nome Idade
# 0 Ana 21
# 1 Bruno 20
# 2 Carla 22

• Note que o DataFrame criado possui as colunas com nomes indicados nas
chaves do dicionário.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

• DataFrames permitem a criação de rótulos personalizados para as linhas e


para as colunas de forma a facilitar o acesso aos dados.
import pandas as pd
dados = [('Ana', 21), ('Bruno', 20), ('Carla', 22)]
colunas = ['Nome', 'Idade']
linhas = ['A', 'B', 'C']
df = pd.DataFrame(data = dados, columns = colunas ,
index = linhas)
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Objetos do tipo Dataframe possuem atributos que são bastante úteis:


• index: retorna os rótulos das linhas em formato de lista.
• columns: retorna os rótulos das colunas em formato de lista.
• ndim: retorna o número de dimensões do DataFrame.
• shape: retorna o tamanho de cada uma das dimensões em um formato de
tupla.
• size: retorna o número de elementos (células) do DataFrame.
• empty: retorna se o DataFrame está vazio (True) ou não (False).
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
print(df.ndim)
#2
print(df.shape)
# (3, 2)
print(df.size)
#6
print(df.empty)
# False
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
print(df.ndim)
#2
print(df.shape)
# (3, 2)
print(df.size)
#6
print(df.empty)
# False
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

A forma de acessar um dado de um DataFrame por meio de índices é a


seguinte:
dataframe[<coluna>][<linha>]

import pandas as pd
dados = [('Ana', 21), ('Bruno', 20), ('Carla', 22)]
df = pd.DataFrame(data = dados)
print(df)
#01
# 0 Ana 21
# 1 Bruno 20
# 2 Carla 22
print(df[0][0], df[0][1], df[0][2])
# Ana Bruno Carla
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

• Os DataFrames possuem indexadores para seleção de dados.


• Esses indexadores fornecem uma forma fácil e rápida de selecionar um
conjunto de dados de um DataFrame.
• Alguns deles são:
• T: usado para transpor linhas e colunas.
• at: acessa um único elemento utilizando rótulos.
• iat: acessa um único elemento utilizando índices.
• loc: seleção de elementos utilizando rótulos.
• iloc: seleção de elementos utilizando índices.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

O indexador T retorna um DataFrame onde as linhas do Dataframe original


são transformadas em colunas.

import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
print(df.T)
#ABC
# Nome Ana Bruno Carla
# Idade 21 20 22
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

O indexador at acessa um único elemento do DataFrame utilizando o rótulo


da linha e da coluna.

import pandas as pd
print(df)
Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
df.at['C', 'Nome']
# 'Carla'
df.at['C', 'Idade']
# 22
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

• O indexador iat acessa um único elemento do DataFrame utilizando os


índices da linha e da coluna

import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
print(df.iat[0, 0])
# Ana
print(df.iat[0, 1])
# 21
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

O indexador loc seleciona um conjunto de linhas e colunas através dos


rótulos ou por uma lista de valores booleanos

import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
print(df.loc[['A', 'C']])
# Nome Idade
# A Ana 21
# C Carla 22
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Mais exemplos com o indexador loc.

import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
print(df.loc[[True , False , True]])
# Nome Idade
# A Ana 21
# C Carla 22
print(df.loc[[True , False , True], 'Nome'])
# A Ana
# C Carla
# Name: Nome, dtype: object
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
O indexador iloc seleciona um conjunto de linhas e colunas baseado
unicamente em índices.
import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
print(df.iloc[-1])
# Nome Carla
# Idade 22
# Name: C, dtype: object
print(df.iloc[[0,2],0])
# A Ana
# C Carla
# Name: Nome, dtype: object
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Manipulação de Dados em um DataFrame

Para adicionar uma nova coluna ao DataFrame basta atribuir ao rótulo da


coluna desejada um valor padrão ou uma lista com os valores desejados.
• Associando um valor padrão:
df [<novo rótulo>] = <valor_padrão>

• Associando valores específicos para cada uma das linhas:


df[<novo rótulo>] = [<valor_1>, <valor_2>,..., <valor_n>]

• O mesmo processo pode ser aplicado para modificar uma coluna já


existente.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
import pandas as pd
print(df)
# Nome Idade
# A Ana 21
# B Bruno 20
# C Carla 22
df['Sexo'] = 'F'
print(df)
# Nome Idade Sexo
# A Ana 21 F
# B Bruno 20 F
# C Carla 22 F
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Para adicionar uma ou mais novas linhas ao DataFrame é possível utilizar o


método append.

• O método append cria um novo DataFrame adicionando no final os novos


valores.

• Para isso, o método recebe como parâmetro um outro DataFrame ou lista


com os novos valores.

• Caso os rótulos das linhas não sejam compatíveis, o parâmetro


ignore_index deve ser atribuido como True para que os rótulos
personalizados das linhas sejam ignorados.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

import pandas as pd
print(df1)
# Nome Idade Sexo
# A Ana 21 F
# B Bruno 20 M
dados = [ {'Nome': 'Carla', 'Idade': 22, 'Sexo': 'F'},
{'Nome': 'Daniel', 'Idade': 18, 'Sexo': 'M'} ]
df2 = df1.append(dados, ignore_index = True)
print(df2)
# Nome Idade Sexo
# 0 Ana 21 F
# 1 Bruno 20 M
# 2 Carla 22 F
# 3 Daniel 18 M
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL

Os indexadores loc e iloc também podem ser utilizados para modificar uma
linha já existente.
• Para isso basta atribuir os novos valores desejados ou um valor padrão.
• O indexador loc também pode ser utilizado para adicionar uma nova linha
no final do DataFrame de forma similar.

• Valor padrão para todas as colunas:


df.loc[<rótulo>] = <valor_padrão>
df.iloc[<linha>] = <valor_padrão>

• Valores específicos para cada coluna:


df.loc[<rótulo>] = [<valor_1,<valor_2 ,...,<valor_n>]
df.iloc[<linha>] = [<valor_1,<valor_2 ,...,<valor_n>]
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
• Exemplo de utilização do indexador loc para inserir e alterar linhas:

import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 21 F
# B Bruno 20 M
df.loc['B'] = ['Bento', 22, 'M']
df.loc['C'] = ['Carla', 22, 'F']
df.loc['D'] = ['Daniela', 18, 'F']
print(df)
# Nome Idade Sexo
# A Ana 21 F
# B Bento 22 M
# C Carla 22 F
# D Daniela 18 F
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Removendo Linhas e Colunas de um DataFrame

• É possível remover linhas ou colunas de um DataFrame utilizando o método


drop.
• Alguns dos parâmetros do método drop são:
• index: recebe um rótulo ou uma lista de rótulos das linhas que serão
removidas.
• columns: recebe um rótulo ou uma lista de rótulos das colunas que serão
removidas.
• inplace: determinar se as mudanças desem ser aplicadas diretamente no
DataFrame ou em uma cópia (valor padrão é False).
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Exemplo de utilização método drop:

import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
# C Carla 20 F
# D Daniel 18 M
df.drop(index = ['A', 'D'], columns = ['Sexo'],
inplace = True)
print(df)
# Nome Idade
# B Bruno 19
# C Carla 20
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
• A biblioteca pandas permite utilizar operadores lógicos e aritméticos em
colunas inteiras de um DataFrame.
• Alguns exemplos de operadores: • +, += • -, -= • *, *= • /, /= • ==, >=, <=, !=, >, <

Exemplo de como aumentar em 1 ano a idade de todas as pessoas do


DataFrame.

import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
#C Carla 20 F
# D Daniel 18 M
df['Idade'] += 1
print(df)
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
# Nome Idade Sexo
# A Ana 18 F
# B Bruno 20 M
# C Carla 21 F
# D Daniel 19 M

Como resultado da aplicação de um operador lógico uma lista de booleanos


é obtida representando a resposta para cada linha do DataFrame. • Exemplo
de como verificar as pessoas que já atingiram a maioridade penal.

import pandas as pd
print(df)
Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
# C Carla 20 F
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
# D Daniel 18 M
resultado = list(df['Idade'] >= 18)
print(resultado)
# [False , True, True, True]

• A aplicação de operadores lógicos em colunas juntamente com o indexador


loc permite a seleção de dados de uma maneira bastante ágil. • Como visto
anteriormente, o resultado da aplicação de operadores lógicos em colunas é
uma lista de booleanos representando as linhas que se adequam ao critério
de seleção. • O indexador loc permite utilizar como parâmetro uma lista com
valores booleanos que representam as linhas que serão selecionadas.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Exemplo de como selecionar do DataFrame as pessoas que já atingiram a
maioridade penal.

import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
# C Carla 20 F
# D Daniel 18 M
resultado = list(df['Idade'] >= 18)
print(df.loc[resultado])
# Nome Idade Sexo
# B Bruno 19 M
# C Carla 20 F
# D Daniel 18 M
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
• Um DataFrame pode ser ordenado utilizando o método sort_values.
• O método sort_values possui alguns parâmetros:
• by: string ou lista de strings especificando os rótulos que serão utilizados
como chave para a ordenação.
• axis: eixo de ordenação vertical (0, padrão) ou horizontal (1).
• ascending: ordenação crescente ou decrescente (padrão: True).
• kind: algoritmo de ordenação que será utilizado (padrão: quicksort).
• inplace: define se a ordenação deve ser aplicada diretamente no DataFrame
ou em uma cópia (padrão: False).
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Exemplo de ordenação de um DataFrame.

import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
# C Carla 20 F
# D Daniel 18 M
df.sort_values(by = 'Idade', ascending = False , inplace = True)
print(df)
# Nome Idade Sexo
# C Carla 20 F
# B Bruno 19 M
# D Daniel 18 M
# A Ana 17 F
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
• É possível também ordenar um DataFrame pelos seus rótulos utilizando o
método sort_index.
• O método sort_index possui alguns parâmetros:
• axis: eixo de ordenação vertical (0, padrão) ou horizontal (1).
• ascending: ordenação crescente ou decrescente (padrão: True).
• kind: algoritmo de ordenação que será utilizado (padrão: quicksort).
• inplace: define se a ordenação deve ser aplicada diretamente no DataFrame
ou em uma cópia (padrão: False).
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Exemplo de ordenação de um DataFrame pelos rótulos das colunas.
import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
# C Carla 20 F
# D Daniel 18 M
df.sort_index(axis = 1, inplace = True)
print(df)
# Idade Nome Sexo
# A 17 Ana F
# B 19 Bruno M
# C 20 Carla F
# D 18 Daniel M
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
A biblioteca pandas possui vários métodos para realização de cálculos em
colunas:
• abs: retorna uma lista com os valores absolutos da coluna.
• count: realiza a contagem de quantas células da coluna possuem valores
disponíveis.
• nunique: conta os valores distintos na coluna.
• sum: retorna a soma dos valores da coluna.
• max: retorna o maior valor da coluna.
• min: retorna o menor valor da coluna.
• mean: computa a média dos valores da coluna.
• median: calcula a mediana dos valores da coluna.
• copy: retorna uma cópia do DataFrame.
• head: retorna as n primeiras linhas do DataFrame (valor padrão: n = 5).
• tail: retorna as n últimas linhas do DataFrame (valor padrão: n = 5).
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Exemplo de métodos aritméticos.
import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
# C Carla 20 F
# D Daniel 18 M
print(df.Idade.count())
#4
print(df.Idade.sum())
# 74
print(df.Idade.max())
# 20
print(df.Idade.min())
# 17
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
print(df.Idade.mean())
# 18.5
print(df.Idade.median())
# 18.5

A biblioteca pandas possui vários métodos para aplicação em matrizes:


• add: soma os elementos das mesmas posições das matrizes.
• sub: subtrai os elementos das mesmas posições das matrizes.
• div: realiza a divisão real entre os elementos das mesmas posições das
matrizes.
• mul: multiplica os elementos das mesmas posições das matrizes.
• eq: verifica se os elementos das mesmas posições das matrizes são iguais.
• ne: verifica se os elementos das mesmas posições das matrizes são
diferentes.
• dot: realiza a multiplicação das matrizes.
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Importando e Exportando Dados

A biblioteca pandas fornece uma forma rápida e fácil para exportar os dados
de um DataFrame para diferentes formatos.
• Entre os diversos formatos disponíveis iremos focar no formato CSV
(Comma-Separated Values, ou Valores Separados por Vírgulas).
• Para realizar essa tarefa temos o método to_csv.
• Alguns dos parâmetros desse método são:
• path_or_buf: caminho ou buffer onde o arquivo deve ser salvo.
• sep: caractere separador do arquivo (o padrão é a vírgula).
• header: define se os rótulos das colunas devem ser inseridos no arquivo ou
não (padrão: True).
• index: define se os rótulos das linhas devem ser inseridos no arquivo ou não
(padrão: True).
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
• Exemplo de como exportar os dados de um DataFrame para um arquivo
CSV.

import pandas as pd
print(df)
# Nome Idade Sexo
# A Ana 17 F
# B Bruno 19 M
# C Carla 20 F
# D Daniel 18 M
df.to_csv('dados.csv')
BIBLIOTECAS EXTERNAS E SISTEMA OPERACIONAL
Para importar um arquivo CSV a biblioteca pandas fornece a função
read_csv.
• Alguns dos parâmetros desse método são:
• filepath_or_buffer: caminho ou buffer até o arquivo CSV.
• sep: caractere separador do arquivo (o padrão é a vírgula).
• names: lista de rótulos para serem utilizados nas colunas.
• header: linha do arquivo CSV para ser utilizada como rótulos para as
colunas.
• index_col: coluna do arquivo CSV para ser utilizada como rótulos para as
linhas

Com isso vimos cfomo trabalhar com DataFrames, conceito crucial para
trabalhar com análise de dados utilizando python.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Neste conteúdo, veremos como o Python pode se interligar com diversas áreas. Até o
momento no seu curso, foram apresentados os conceitos básicos da linguagem e um pouco
de aplicações externas, como, por exemplo, a utilização dos pacotes externos, como fizemos
com o Pygeocoder. A missão, a partir de agora, édemonstrar as várias áreas de atuação em
que poderemos utilizar Python.

Agora entenderemos como ele pode interagir com alguns protocolos, saberemos mais
adiante como ele será utilizado com IoT, um pouco mais à frente,também verificaremos a
ligação do Python com Inteligência Artificial e finalizaremos o conteúdo deste ano em Python
comunicando-se com Cybersecurity junto a ferramentas de pentest. Então, agora é abrir o seu
IDE e vamos codar.

Tudo começa com a biblioteca “socket”. A biblioteca socket é integrante do conjunto de


bibliotecas-padrão que já fazem parte da PVM do Python, ou seja, diferentemente da
Pygeocoder, ela não precisa ser instalada por meio do comando “pip”, apresentado
anteriormente. Para utilizar essa biblioteca, basta realizar o import na primeira linha do seu
código, da seguinte forma:
import socket
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Podemos observar que o pacote “datetime” irá nos permitir recuperar a data
completa de acordo com o sistema operacional, assim como: dia, mês, ano, hora,
minuto e segundo. Essa sequência também poderá nos ajudar, por exemplo, na
montagem de um inventário. Já o pacote “getpass” nos propicia retornar o usuário
logado no momento, o que pode nos auxiliar, por exemplo, no desenvolvimento de
uma ferramenta de auditoria, em que saberemos as ações que determinado usuário
realizou, assim como estabelecer se o usuário está em um dia/horário que deve
possuir ou não acesso. Se a clínica não abre aos domingos, poderemos bloquear
todos os usuários, exceção ao administrador, o acesso ao sistema, máquina ou
qualquer outro item que faça parte da rede, que desejarmos.
Mas o “getpass” também nos proporciona ter acesso a outro recurso bem
interessante. Observe o código seguinte e o considere como parte de uma ferramenta:
usuario=input("Digite o usuário: ").upper()
senha= input("Digite a senha: ")
if usuario == "BITMED" and senha == "FiAp1222":
print("Usuário logado")
else:
print("Login Negado")
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Esse código é bem simples, estamos somente capturando um usuário e senha
e verificando se é o usuário (“BITMED”) com a senha válida (“FiAp1222”). Somente
se usuário e senha coincidirem, o usuário terá acesso e será logado. Mas observe
que, ao digitar a senha, essa será apresentada na tela enquanto o usuário digitar, ou
seja, nada seguro, não é mesmo? É aí que entra a outra função do “getpass”. Veja,
agora, o código alterado (digite-o em um novo arquivo chamado “Login.py”):

import getpass
usuario = input("\nDigite o usuário: ").upper()
senha = getpass.getpass("Digite a senha: ")
if usuario == "BITMED" and senha == "FiAp1222":
print("Usuário logado")
else:
print("Login Negado")
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Esse código é bem simples, estamos somente capturando um usuário e senha
e verificando se é o usuário (“BITMED”) com a senha válida (“FiAp1222”). Somente
se usuário e senha coincidirem, o usuário terá acesso e será logado. Mas observe
que, ao digitar a senha, essa será apresentada na tela enquanto o usuário digitar, ou
seja, nada seguro, não é mesmo? É aí que entra a outra função do “getpass”. Veja,
agora, o código alterado (digite-o em um novo arquivo chamado “Login.py”):

import getpass
usuario = input("\nDigite o usuário: ").upper()
senha = getpass.getpass("Digite a senha: ")
if usuario == "BITMED" and senha == "FiAp1222":
print("Usuário logado")
else:
print("Login Negado")
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Caso você execute esse código dentro do PyCharm, verá que o comportamento
do sistema não está adequado (dependendo do seu sistema operacional). Você digita
o usuário, ele muda de linha e permanece solicitando o usuário, até que você encerre
o código manualmente. Isso ocorrerá porque a IDE (ou até mesmo o ambiente IDLE
do Python) não consegue utilizar o método getpass() para a emissão de caracteres.
Somente quando o código for executado fora da IDE é que ele irá funcionar
perfeitamente. Logo, teremos duas opções: a primeira seria você ir até o console do
seu sistema operacional, se deslocar até a pasta do seu arquivo e, então, compilar o
código-fonte; a outra, mais simples, é que podemos simular a execução no console
dentro do Python, para isso, observe a seguinte figura:

De acordo com a imagem, clique sobre o dropbox, no qual aparece o nome do


seu arquivo (Login), em seguida, clique sobre a opção “Edit Configurations”, surgirá,
então, a seguinte caixa de diálogo, marque a opção que está destacada:

Clique sobre o botão “OK” e, em seguida, execute o seu código. Você verá, na
parte inferior, que o seu código será executado como se estivesse sendo compilado
no console do seu sistema operacional. Agora, no momento da digitação, ele não só
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Você deve estar se perguntando: por que preciso importar essa biblioteca?
Qual a sua finalidade? Pois bem, essa é a biblioteca que será responsável por criar ferramentas
e estabelecer comunicação entre dois processos, ou mais, que podem estar em uma rede de
computadores. Por isso, vamos relembrar os principais protocolos envolvidos em uma
transmissão de dados entre computadores:
• IP: que representa o endereço do qual partiu ou para o qual irá determinado pacote de
dados, ou seja, o endereçamento lógico;
• TCP: protocolo de transporte que possui maior confiabilidade na entrega dos pacotes, devido
ao processo de “handshake” que ele realiza; e
UDP: protocolo de transporte que possui maior velocidade, porém menor confiabilidade de
entrega (quando comparado ao TCP), uma vez que ele não realiza “handshake”.
Claro que essas definições apenas pretendem relembrar os conceitos básicos desses
protocolos. Vejamos um primeiro exemplo para recuperarmos o endereço IP por meio do
DNS:
• Crie um novo diretório chamado: Capitulo7_Socket, dentro dele, crie um arquivo do tipo
“Python File”, chamado: Socket.py, e digite o seguinte código:
PROTOCOLO DE COMUNICAÇÃO E PYTHON
import socket
resp="S"
while(resp=="S"):
url=input("Digite uma url: ")
ip=socket.gethostbyname(url)
print("O IP referente à url informada é: ", ip)
resp=input("Digite <s> para continuar: ").upper()

Nesse exemplo, estamos:


• Importando a biblioteca socket.
• Criando uma variável para controlar o nosso laço, que virá na sequência.
• Criando um laço para que, enquanto você digita a letra “s”, o código continue lhe
perguntando uma url e exibindo o seu IP. O laço somente será encerrado caso digite algo
diferente de “s” ou se digitar uma url inexistente.
• Dentro do laço, temos uma variável chamada “url” que simplesmente irá
armazenar o domínio que está tentando localizar o IP, por isso, digite algo
como: www.globo.com.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Logo depois, colocamos a variável “ip” para receber o conteúdo do método gethostbyname(),
que será o IP baseado no valor da variável “url” que está dentro dos parênteses, ou seja,
gethostbyname() é um método pertencente à classe socket, que recebe uma URL e retorna o
IP.

Por fim, exibimos o IP na tela para o usuário.

Simples, não é mesmo? Mas até o momento vimos o socket somente agindo
junto ao protocolo IP, que, por sua vez, ainda necessita de uma porta para que
pacotes possam ser direcionados de maneira íntegra e correta.
Podemos identificar as portas da nossa máquina que estão sendo utilizadas
para serviços, como domínio, http e ftp, por exemplo. Crie um novo arquivo “Python
File” com o nome “Portas.py” e digite o código a seguir:

import socket
print(socket.getservbyname("domain"))
print(socket.getservbyname("http"))
print(socket.getservbyname("ftp"))
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Com a execução desse código, teremos o retorno das portas que estamos
disponibilizando para: domínio (por padrão 53), usado para resolver a conversão
entre DNS e IP; HTTP (por padrão 80), usado para navegar nas páginas WEB; e
FTP (por padrão 21), usado para transferência de arquivos.

Agora, que já sabemos como recuperar um IP e como identificar as portas, já


é possível estabelecer um diálogo entre dois processos que podem estar sendo
executados em máquinas separadas dentro de uma mesma rede, ou não; os
processos podem estar rodando em um mesmo computador.

Preparação do servidor
Vamos preparar duas ferramentas, uma será utilizada para ficar no servidor,
isso significa que será a ferramenta que ficará escutando e atendendo aos pedidos
dos clientes. A segunda ferramenta deverá ficar nos clientes, ou seja, é a ferramenta
que irá fazer as solicitações para o servidor.

Vamos começar criando um arquivo “Python File”, chamado Servidor.py, que


a princípio deverá conter os seguintes comandos:
PROTOCOLO DE COMUNICAÇÃO E PYTHON
from socket import *
servidor="127.0.0.1"
porta=43210
obj_socket = socket(AF_INET, SOCK_STREAM)
obj_socket.bind((servidor,porta))
obj_socket.listen(2)
print("Aguardando cliente....")
while True:
con, cliente = obj_socket.accept()
print("Conectado com: ", cliente)
while True:
msg_recebida = str(con.recv(1024))
print("Recebemos: ", msg_recebida)
msg_enviada = b'Olah cliente'
con.send(msg_enviada)
break
con.close()
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Vamos a uma explicação sobre o que está ocorrendo nesse código:
• Primeiramente, importamos todas (*) as funções da biblioteca “socket”, isso será preciso para
que possamos criar objetos do tipo “socket”.Criamos duas variáveis, “servidor” e “porta”, para
armazenarmos esses dois dados que serão utilizados posteriormente; em “servidor”, poderíamos
utilizar também a palavra “localhost” para identificarmos que o servidor é a
própria máquina que está executando o código, o que também é representado pelo endereço
“127.0.0.1”, que foi aqui utilizado. Em “porta”,escolhemos uma porta representada por um número
inteiro entre 0 e 65535, em que normalmente as portas entre 0 e 1023 são portas
utilizadas, por padrão, para atribuições de serviços conhecidos por meio do sistema operacional.
• Na quarta linha, criamos o nosso objeto socket “obj_socket”, por meio da função “socket()”, que
exige dois parâmetros: o primeiro definirá a família responsável por identificar os pacotes. Para o
nosso exemplo, definimos como AF_INET, o que significa que iremos utilizar a identificação do
emissor/receptor do(s) pacote(s) via DNS ou número IP (poderíamos utilizar a constante AF_UNIX,
o que mudaria a forma de identificar a origem/destino do(s) pacote(s)). Já o segundo parâmetro
refere-se ao transporte desse pacote, que pode ser SOCK_STREAM, que representa o
protocolo TCP (o que nós optamos) ou SOCK_DGRAM, que representa o
protocolo de transporte UDP.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Na próxima linha, fazemos a associação no nosso objeto socket com o nosso servidor e porta.
• Na linha em que utilizamos a função “listen()”, estamos definindo o máximo de clientes que o
nosso servidor irá atender simultaneamente, para o nosso caso, definimos que serão, no máximo,
dois (2) clientes.
• Montamos, na sequência, dois laços infinitos (enquanto for verdadeiro): no primeiro,
aguardamos a chamada de um cliente (por meio da função accept()), assim que tivermos,
receberemos uma tupla e iremos direcionar a identificação do cliente para a variável “cliente” e a
identificação da conexão para a variável “con” e, então, iremos exibir a identificação do
nosso cliente;
• No segundo laço, aguardando uma solicitação que pode ser transmitida
em pacotes de 1024 bytes, exibimos a mensagem recebida e geramos uma mensagem para
enviar no formato de “bytes” (por isso, a mensagem começa com “b” e, em seguida, a string que se
deseja), enviamos por meio do método “send()” e encerramos esse segundo laço while.
• Finalmente, fechamos a conexão e voltamos a aguardar uma nova conexão.

Todos os dados transmitidos via socket devem estar no formato byte. O socket
não envia nem recebe dados strings, por exemplo.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Na próxima linha, fazemos a associação no nosso objeto socket com o nosso servidor e porta.
• Na linha em que utilizamos a função “listen()”, estamos definindo o máximo de clientes que o
nosso servidor irá atender simultaneamente, para o nosso caso, definimos que serão, no máximo,
dois (2) clientes.
• Montamos, na sequência, dois laços infinitos (enquanto for verdadeiro): no primeiro,
aguardamos a chamada de um cliente (por meio da função accept()), assim que tivermos,
receberemos uma tupla e iremos direcionar a identificação do cliente para a variável “cliente” e a
identificação da conexão para a variável “con” e, então, iremos exibir a identificação do
nosso cliente;
• No segundo laço, aguardando uma solicitação que pode ser transmitida
em pacotes de 1024 bytes, exibimos a mensagem recebida e geramos uma mensagem para
enviar no formato de “bytes” (por isso, a mensagem começa com “b” e, em seguida, a string que se
deseja), enviamos por meio do método “send()” e encerramos esse segundo laço while.
• Finalmente, fechamos a conexão e voltamos a aguardar uma nova conexão.

Todos os dados transmitidos via socket devem estar no formato byte. O socket
não envia nem recebe dados strings, por exemplo.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Preparação do cliente

Vamos preparar um código que permita a comunicação de um cliente


qualquer, que faça parte da rede, com o nosso servidor. Para isso, crie um arquivo
“Python File”, nomeado como Cliente.py, e monte o código a seguir:

from socket import *


servidor="127.0.0.1"
porta=43210
msg = bytes(input("Digite algo: "), 'utf-8')
obj_socket=socket(AF_INET, SOCK_STREAM)
obj_socket.connect((servidor,porta))
obj_socket.send(msg)
resposta=obj_socket.recv(1024)
print("Recebemos: ", resposta)
obj_socket.close()
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Detalhando as linhas do código apresentado:
• Importamos as funções da biblioteca socket e criamos duas variáveis, uma para representar o
servidor, caso o servidor não fosse a máquina local, poderíamos definir o IP do servidor
externo, se fosse o caso. Cuidado ao definir a porta, deve ser a mesma em que inicializamos o
servidor.
• Na quarta linha, definimos o conteúdo da variável “msg”, por meio de uma entrada do usuário
(input). Observe que utilizamos a função “bytes()” para converter o conteúdo do input, ou seja,
a string para o formato bytes, mais uma vez, lembrando: o socket transmite somente dados do
tipo byte. A função “bytes()” possui o segundo parâmetro que faz referência ao padrão
de caracteres “utf-8”.

• As três próximas linhas são referentes à criação do objeto socket (por meio da função
“socket()”), à conexão com o servidor, por meio da função “connect()”, e, finalmente, enviando
uma mensagem para o servidor, utilizando o método “send()”.

A variável resposta recebe o dado enviado pelo servidor, limitando o tamanho para 1024 bytes.

• E finalizamos o código, exibindo a resposta e fechando conexão.


PROTOCOLO DE COMUNICAÇÃO E PYTHON
Agora, surge o momento da execução. Caso você tente executar o “Cliente.py”, primeiramente,
após digitar o dado a ser transmitido para o servidor, irá receber uma mensagem de erro,
conforme aponta a imagem a seguir, pois o servidor não está com a porta disponível, uma vez
que você não o executou ainda.

Dessa forma, execute primeiramente a versão do nosso código que está no


arquivo “Servidor.py”, seu console ficará da seguinte forma:

Após colocar o servidor em execução, execute o nosso arquivo “Cliente.py”,


ele irá solicitar o dado a ser transmitido. Digite o dado que deseja transmitir e receba
a resposta do servidor, conforme apresentado na figura Executando o Cliente :

De acordo com o destaque da imagem, você poderá ver o que chegou ao


servidor e como continua o seu status, clicando na guia “Servidor”, conforme
apresentado na figura Resposta do Servidor
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Repare que você pode seguir executando o cliente e passando mensagens
para ele, que irá receber sua mensagem e sempre retornará a mensagem “Olah
Cliente”. Observe, também, na guia da execução do servidor, que mostra o IP do
cliente e a porta, como não definimos uma porta para o cliente, o próprio socket
gerou e disponibilizou, por meio de uma porta aleatória.
O desafio agora é: você consegue montar um “chat” entre o cliente e o
servidor? Ou seja, você pode enviar um dado para o servidor, faça o mesmo com o
servidor, e deixe o cliente dentro de um laço infinito para que possam conversar.
Tente fazer isso, antes de continuar para o próximo tópico, no qual terá a resposta.

Chat Python

Vamos demonstrar, agora, como ficará o código do cliente e do servidor, a fim


de montarmos o nosso chat. Vamos começar pelo servidor:
PROTOCOLO DE COMUNICAÇÃO E PYTHON
from socket import *
servidor="127.0.0.1"
porta=43210
obj_socket = socket(AF_INET, SOCK_STREAM)
obj_socket.bind((servidor,porta))
obj_socket.listen(2)
print("Aguardando cliente....")
while True:
con, cliente = obj_socket.accept()
print("Conectado com: ", cliente)
while True:
msg_recebida = str(con.recv(1024))
print("Recebemos: ", str(msg_recebida)[2:-1])
msg_enviada = bytes(input("Sua resposta: "), 'utf-8')
con.send(msg_enviada)
break
con.close()
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Em relação ao novo código do servidor apresentado, alteramos somente o conteúdo do
segundo while, no qual estamos convertendo a mensagem que recebemos para string
(str(msg_recebida) e, em seguida, fazendo um slice ([2:-1]) dela, em que pegamos do segundo
caractere até o último caractere da string, com isso, quando recebermos, por exemplo: b’olah
servidor’, será exibido apenas: olah servidor. Alteramos também a linha referente ao conteúdo
da variável msg_enviada, que antes era uma mensagem única e agora é definida por meio do
input(), no qual o usuário irá digitar o que desejar.
Em relação ao lado do cliente, vejamos como ficou o código:

from socket import *


servidor="127.0.0.1"
porta=43210
while True:
obj_socket = socket(AF_INET, SOCK_STREAM)
obj_socket.connect((servidor, porta))
msg = bytes(input("Sua mensagem: "), 'utf-8')
obj_socket.send(msg)
resposta=obj_socket.recv(1024)
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Do lado do cliente, foi incluído o laço while, para que o cliente possa mandar mais que uma
mensagem ao servidor, deixamos de fora do while somente a definição do servidor (ip e porta)
e o encerramento da conexão. A resposta do servidor também foi convertida para string e foi
realizado o slice da string para considerar somente a mensagem válida.
Execute o servidor, em seguida, o cliente e veja que poderá trocar
mensagens entre os dois processos. Se estiver em um ambiente com uma rede de
computadores, poderá verificar o funcionamento desses códigos em equipamentos
distintos. Claro que muitas aprimorações podem ser realizadas, como, por exemplo,
encerrar a conversa do lado do cliente, para isso, bastaria sair do laço infinito:
from socket import *
servidor="127.0.0.1"
porta=43210
while True:
obj_socket = socket(AF_INET, SOCK_STREAM)
obj_socket.connect((servidor, porta))
msg = bytes(input("Sua mensagem: "), 'utf-8')
obj_socket.send(msg)
resposta=obj_socket.recv(1024)
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Adicionamos somente as linhas que estão em vermelho, quando digitarmos
“fim” receberemos a mensagem do servidor e, então, a aplicação do lado do cliente
será encerrada. Já do lado do servidor, ele continuará escutando novos clientes.
Assim, poderíamos também pensar ainda em muitas melhoras, mas a ideia
principal do capítulo é demonstrar como podemos estabelecer comunicação entre
dois equipamentos que estejam conectados em um mesmo ambiente de rede, além,
é claro, de apresentar a funcionalidade para transmissão de dados entre
computadores. Todos os conceitos apresentados serão extremamente úteis para o
desenvolvimento de ferramentas em Python que irão permitir controlar e testar
informações que estarão trafegando na sua rede.
Como sugestão para estudos futuros, caso você precise rodar uma aplicação
cliente-servidor em um ambiente de alta concorrência, ou seja, com muitos clientes
conectando-se simultaneamente ao servidor, é possível que você tenha que optar
por trabalhar com “threads” (processos dentro do sistema operacional). Nesse caso,
você tornaria cada conexão com o cliente uma “thread” e, com isso, o
gerenciamento passaria a ser escalável e propício para a alta concorrência ou ainda
utilizar a biblioteca “socketserver” junto com “threads”, assim suas requisições para o
servidor estariam ainda mais sob controle. Não abordaremos esses modos por
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Protocolo UDP
Como você já viu anteriormente, o protocolo UDP não é confiável em relação
à garantia de que os dados cheguem até o destino, mas, como contraponto,
sabemos que esse protocolo entrega de maneira muito mais rápida, quando
comparado ao TCP. As aplicações desse protocolo estão mais voltadas para
ambientes que utilizem “streaming” de vídeos e/ou áudios ou até mesmo ambientes
de jogos online, que têm a velocidade como algo primordial para a jogabilidade.
Veremos um pequeno exemplo, utilizando o protocolo UDP para que possamos completar a
manipulação dos dois principais protocolos de transporte dentro do Python.
Vamos iniciar, montando o código do servidor. Para isso, crie o arquivo do tipo “Python File”,
chamado Servidor_UDP.py, e monte o seguinte código:
from socket import *
servidor="127.0.0.1"
porta=43210
obj_socket = socket(AF_INET, SOCK_DGRAM)
obj_socket.bind((servidor,porta))
print("Servidor pronto....")
while True:
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Vamos às descrições do código informado:
• Começamos importando e estabelecendo o endereço do servidor e a porta
que será utilizada para a comunicação.
• Na terceira linha, alteramos o segundo parâmetro para DGRAM, o que
determina que utilizaremos o protocolo de transporte UDP.
• Realizamos o bind do servidor com a porta e endereço especificados.
• Não realizamos o listen(), uma vez que não há necessidade de
confiabilidade na troca de dados, por isso, já entramos no laço.
• Dentro do laço, aguardamos os dados do cliente, com o tamanho limitado
a 65535 (tamanho máximo), prática bem comum, devido à aplicação
cotidiana desse protocolo. Perceba que o método agora utilizado é o
recvfrom(), que não possui ligação com objeto de conexão.

Os dois prints() a seguir servem para exibir a origem e, em seguida, os


dados. Perceba que agora não utilizamos mais a conversão para string e o
slice, em vez disso, usamos a função “decode()”, que exibe os dados bytes
no formato string. Essa forma também poderia ser utilizada junto ao
protocolo TCP.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Recebemos a resposta que o servidor deseja passar e encaminhamos para o cliente por
meio do método “sendto()”, que é formado por dois parâmetros: o primeiro é a mensagem
propriamente dita, na qual, dessa vez, utilizamos o método “encode()” para converter de
string para byte; e o segundo parâmetro é a origem para a qual desejamos enviar a
mensagem. Por fim, finalizamos a conexão do socket.
Crie, agora, um novo arquivo “Python File”, chamado Cliente_UDP.py, e digite o código a
seguir:

from socket import *


servidor="127.0.0.1"
porta=43210
obj_socket = socket(AF_INET, SOCK_DGRAM)
obj_socket.connect((servidor, porta))
saida=""
while saida!="X":
msg = input("Sua mensagem: ")
obj_socket.sendto(msg.encode(), (servidor,porta))
dados, origem = obj_socket.recvfrom(65535)
PROTOCOLO DE COMUNICAÇÃO E PYTHON
As alterações realizadas nesse código estão destacadas na cor vermelha.
Observe que alteramos o segundo parâmetro da função “socket()” para UDP. O
método “sendto()” também foi utilizado, pois, diferentemente do método “send()”
utilizado no TCP, o “sendto()” possui dois parâmetros: a mensagem e o destino da
mensagem. A captura do servidor também foi alterada para o método “recvfrom()”.

Muitas são as possibilidades a partir do conteúdo apresentado, até mesmo


criar um “bot”, dentro de um ambiente controlado, no qual o cliente faz uma
pergunta, que a aplicação do servidor verifica e, com base em uma análise, envia a
resposta para o cliente. Por exemplo, o cliente pergunta: “Qual o e-mail do
administrador?”, “Qual o ramal do departamento de pessoal?”, “Quem não efetuou
login ainda hoje?”.

O bot pode fazer uma análise sobre as palavras recebidas, então, realizar
algum processamento e responder de acordo com a análise/processamento dos dados que
foram recebidos, ajudando, de maneira automática, todos os clientes que
estiverem na rede. Essa ideia pode ser ainda mais aprimorada e, por exemplo, fazer
com que o servidor esteja conectado a um banco de dados que armazenará
PROTOCOLO DE COMUNICAÇÃO E PYTHON
O mundo não é feito só de sockets

Além da biblioteca “sockets”, que, como já vimos, permite a troca de pacotes


entre equipamentos que estão conectados em uma mesma rede por meio dos
protocolos TCP e UDP, o Python possui muitas outras bibliotecas que permitem
manipular outros protocolos, como, por exemplo, SMTP para e-mails, HTTP para
envio ou recebimento de dados de uma página WEB, entre outros. Claro que não
iremos apresentar todos, isso demandaria uma disciplina inteira.
Mas, a fim de complementarmos um pouco mais e consolidarmos o poder do
Python no meio dos protocolos, iremos abordar um pouco agora sobre o FTP (File
Transfer Protocol), que tem como principal finalidade trocar arquivos entre os
dispositivos que estiverem conectados em uma mesma rede. Uma primeira
observação muito importante: utilize-o com moderação, pois esse protocolo é
inseguro e pode trazer vulnerabilidades para o seu ambiente, daí a importância em
conhecê-lo.
Primeiro, para a manutenção em ambientes legados, em que pode parecer
que está tudo funcional e seguro; e, em segundo lugar, pelo simples fato de ser o
ponto de partida para aqueles que quiserem, posteriormente, se aprofundar no
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Para começar, é importante apontar que, por meio do FTP, poderemos
realizar downloads, uploads, listagem de arquivos e manutenção também dos
diretórios. Outra característica importante para apontarmos neste momento é que o
principal ponto falho de segurança é a forma de envio do usuário e senha que tentarão
realizar o login no servidor FTP, pois não recebem qualquer tipo de criptografia e permitem
que qualquer monitor de tráfego visualize esses dados.

A biblioteca “ftplib” é responsável por permitir a manipulação desse protocolo,


logo, teremos que importá-lo dentro do nosso código. Para começarmos a parte
prática, crie um “Phyton File”, chamado Protocolo_FTP.py, e digite as seguintes
linhas:

from ftplib import *


ftp_ativo=False
ftp = FTP('ftp.ibiblio.org')
print(ftp.getwelcome())
ftp.quit()
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Você já pode executar o seu arquivo, deverá ver uma mensagem do servidor FTP e a
conexão será finalizada na sequência. Caso o código esteja idêntico e apresente qualquer
erro, verifique se o seu computador possui um firewall que esteja bloqueando a conexão
com um servidor FTP ou ainda se a rede em que está conectado (no caso de empresa ou
qualquer outra instituição) permite uma transmissão FTP. Vamos analisar, com um pouco
mais de detalhe, o código proposto anteriormente:

Na primeira linha, fizemos a importação de todas as funções do módulo ftplib, como, por
exemplo, a função FTP(), que permite criar um objeto que representará a conexão
estabelecida.

Na segunda linha, criamos uma variável booleana, ou seja, armazenará somente os valores
“True” ou “False” (cuidado, pois no Python, os valores “True” e “False” devem ser digitados
com a primeira letra maiúscula, diferente dos padrões adotados em outras linguagens).

Essa variável está definida como False, e a utilizaremos posteriormente, para definirmos se
a conexão será ativa ou passiva.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
A conexão ativa era mais utilizada quando a Internet ainda não era tão difundida, pois
permitia que o servidor criasse uma conexão diretamente com o cliente, entretanto, os
clientes passaram a ter firewalls e outros tipos de proteções, o que passou a impedir esse
tipo de solicitação. Então, a utilização da conexão passiva passou a ser mais comum,
representando que o servidor irá liberar uma porta e solicitará o estabelecimento da
conexão para o cliente, por isso, a variável está com o valor False, que representa a conexão
passiva.
Na terceira linha, criamos um objeto para representar uma conexão FTP, para isso,
utilizamos o método “FTP()”, que precisa apenas do endereço do servidor FTP, no exemplo,
utilizamos o endereço “ftp.ibiblio.org”. Caso queira, pode acessá-lo diretamente em seu
browser, por meio do endereço “ftp://ftp.ibiblio.org/”, irá surgir uma imagem como a que
será apresentada logo a seguir.

Na quarta linha, chamamos o método “getwelcome()” do objeto “ftp”, que irá apresentar
uma mensagem-padrão retornada pelo servidor. Essa mensagem pode, por exemplo, ser
útil para informar ao cliente que algum arquivo está indisponível, ou que o servidor está
passando por uma atualização, ou simplesmente ser responsável por um “olá”.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Na última linha, encerramos a conexão.
Este servidor “ibiblio” é público (uma biblioteca pública para compartilhamento
de arquivos digitais) e permite acesso aos seus arquivos de maneira livre. Perceba
que, por intermédio do browser, você pode navegar entre os diretórios,
provavelmente não irá encontrar nada de muito interessante entre os diretórios, e
também baixar os arquivos, algo que iremos fazer por meio do Python para que você
possa automatizar essa ação utilizando uma ferramenta.

from ftplib import *


ftp_ativo=False
ftp = FTP('ftp.ibiblio.org')
print(ftp.getwelcome())
usuario=input("Digite o usuario: ")
senha=input("Digite a senha: ")
ftp.login(usuario, senha)
print("Diretório atual de trabalho: ", ftp.pwd())
ftp.quit()
PROTOCOLO DE COMUNICAÇÃO E PYTHON
O que está destacado na cor vermelha representa o que foi adicionado no nosso código.
Primeiro, podemos observar que criamos duas variáveis para representarem um usuário e
senha, respectivamente (poderíamos, na senha, utilizar a biblioteca “getpass” conforme
apresentado em capítulos anteriores). Na sequência, utilizamos o método “login()”, que é
responsável por estabelecer a conexão com o servidor. Caso você não informe nenhum
usuário e nenhuma senha, entrará no sistema como “usuário anônimo”, esse tipo de usuário
pode ou não ser permitido pelo servidor. Quando executar, não digite nada em usuário e
senha e verá que conseguirá acesso como anônimo. Em seguida, tente executar novamente
e tente digitar um usuário qualquer e uma senha qualquer e verá que não terá acesso. Isso
significa que, para esse servidor, ou você entra como anônimo, e, com certeza, terá
acesso restrito ao conteúdo, ou entra por meio de um usuário previamente cadastrado no
servidor, assim, provavelmente, terá um acesso maior dentro do ambiente.

Seguindo a leitura do código apresentado, na linha do “print()” que foi


adicionado, utilizamos o método pwd() que retorna o endereço atual de trabalho, ou
seja, retorna o diretório em que você se encontra atualmente. Você pode se deslocar
entre os diretórios por meio da função cwd(), conforme apresentamos a seguir:
PROTOCOLO DE COMUNICAÇÃO E PYTHON
from ftplib import *
ftp_ativo=False
ftp = FTP('ftp.ibiblio.org')
print(ftp.getwelcome())
usuario=input("Digite o usuario: ")
senha=input("Digite a senha: ")
ftp.login(usuario, senha)
print("Diretório atual de trabalho: ", ftp.pwd())
ftp.cwd('pub')
print("Diretório corrente: ", ftp.pwd())
ftp.quit()

Como podemos observar, mudamos para o diretório “pub” e, logo depois,


podemos observar, por meio da mensagem do “print()”, que realmente estamos em
outro diretório. Procure acessar o FTP do IBGE e navegar entre os diretórios.
Podemos também listar os arquivos que encontrarmos nos diretórios, antes
de encerrarmos a conexão. Vejamos a seguir:
PROTOCOLO DE COMUNICAÇÃO E PYTHON
from ftplib import *
ftp_ativo=False
ftp = FTP('ftp.ibiblio.org')
print(ftp.getwelcome())
usuario=input("Digite o usuario: ")
senha=input("Digite a senha: ")
ftp.login(usuario, senha)
print("Diretório atual de trabalho: ", ftp.pwd())
ftp.cwd('pub')
print("Diretório corrente: ", ftp.pwd())
print(ftp.retrlines('LIST'))
ftp.quit()

Como podemos perceber na única linha destacada em vermelho, foi só utilizar


o método dir(), que nos foi retornada a lista de arquivos encontrados no diretório
atual, inclusive, com data de criação e tamanho Bem prático, não é mesmo? Você pode
montar um laço permitindo que o usuário digite as pastas que deseja navegar
e visualizar os conteúdos, procure praticar
PROTOCOLO DE COMUNICAÇÃO E PYTHON
E para baixarmos algum arquivo? Primeiro, precisamos entender que tudo o
que for transmitido pelo protocolo é no formato “byte”, assim como vimos nos
protocolos TCP e UDP, e, com certeza, teremos que realizar a conversão para
strings, a fim de que o Python possa interpretá-los e manipulá-los de maneira mais
natural. Entretanto, nem todos os arquivos estarão no formato ASCII, como, por
exemplo, um arquivo zipado. Por isso, deverão ser transmitidos e baixados em
formato de “byte” mesmo. Vejamos, primeiro, o caso de um arquivo ASCII, o arquivo
“README”, que está dentro do diretório-raiz. Crie um novo arquivo “Python File”,
com o nome de “FTP_ASCII.py”, e digite o seguinte código:
import os
from ftplib import *
def escreverLinha(data):
arq.write(data)
arq.write(os.linesep)
ftp_ativo=False
ftp = FTP('ftp.ibiblio.org')
print(ftp.getwelcome())
ftp.login()
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Por meio da análise das primeiras linhas desse código, podemos perceber
que criamos uma função chamada “escreverLinha()”, a qual explicaremos
posteriormente. Conectamo-nos ao servidor “ftp.ibiblio.org”, a mensagem de boas�vindas, e
realizamos o login como “anônimo”. Em seguida, definimos o modo de
conexão, para o nosso caso “passiva”, conforme explicado anteriormente.
Na sequência, abrimos um “with” para criarmos um arquivo, no qual
detalharemos as linhas a seguir:
• Na linha do bloco “with”, definimos que iremos abrir/criar um arquivo
chamado “LEIAME” em modo de escrita, e que, dentro desse bloco, será
identificado como “arq”.
Na linha interna ao bloco “with”, iremos utilizar o método retrlines(), que é
formado por dois parâmetros: no primeiro, devemos especificar o retorno
(RETR) e o nome do arquivo que será retornado ('RETR README'); o
segundo parâmetro representa uma função que criamos no início do
código, a “escreverLinha()”, que receberá o conteúdo da linha
(arq.write(data)) no “arq” e utilizará o separador de linha, identificado por
meio da leitura do sistema operacional, escrevendo o mesmo no “arq”
também (arq.write(os.linesep)), ou seja, cada linha será escrita no
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Por fim, encerramos a conexão.
Quando você executar o arquivo, será gerado, no mesmo diretório do
FTP_ASCII.py, um arquivo chamado LEIAME. Nele, teremos o mesmo conteúdo do
arquivo README, que está no ftp.ibiblio.org.
Agora, vamos realizar o código responsável por baixar um arquivo binário,
como uma imagem, pdf, vídeo ou qualquer outro formato que não seja ASCII. Crie
um novo arquivo do tipo “Python File”, chamado FTP_Binario.py, e digite o código a
seguir:

from ftplib import *


ftp = FTP('ftp.ibiblio.org')
print(ftp.getwelcome())
ftp.login()
ftp.cwd('/pub/linux/logos/pictures')
with open ('pai_do_linux.jpg', 'wb') as arq:
ftp.retrbinary('RETR linus-father-of-linux.jpg', arq.write)
ftp.quit()
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Como não existe a preocupação na separação de linhas (como nos arquivos
ASCII), podemos perceber de pronto que não há a necessidade da função
“escreverLinhas()”, que criamos anteriormente. Para baixar um arquivo binário,
basta, basicamente: criar a conexão (FTP()), estabelecer o login (login()) e definir o
diretório (cwd()). Caso o arquivo não esteja no diretório-raiz e, dentro do “with”,
definir o arquivo de saída e também especificar que será binário por meio da flat
“wb”, ou seja, o arquivo (pai_do_linux.jpg) será criado em modo escrita e também
escrito em binário.Dentro do bloco “with”, utilizamos o método “retrbinary()”, que permite
especificar o arquivo que será lido ('RETR linus-father-of-linux.jpg') e o
arquivo que será escrito (arq.write), depois disso, apenas encerramos a conexão
FTP.
Mais uma vez, ao executar esse arquivo, você verá que foi gerado outro,
“pai_do_linux.jpg”, no mesmo diretório do “FTP_Binario.py”, e que pode ser aberto
normalmente. Pronto, agora você já pode desenvolver uma ferramenta para baixar
arquivos, binários ou não, de um servidor FTP.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Um exemplo FTP mais interativo

Vamos montar um exemplo um pouco mais interativo, para que a ferramenta


fique mais flexível para o usuário e possa também contar com a sua interação. Para
isso, vamos criar um novo arquivo “Python File”, chamado “FTP_Interativo.py”, e
aproveitaremos parte do conhecimento obtido até o momento para montarmos o
código a seguir:

import os
from ftplib import *
ftp_ativo=False
ftp = FTP(input("Digite o FTP que se deseja conectar: "))
print(ftp.getwelcome())
usuario=input("Digite o usuario: ")
senha=input("Digite a senha: ")
ftp.login(usuario, senha)
print("Conexão bem sucedida.\nDiretório atual de trabalho: ", ftp.pwd(),"\n\n")
menu="1"
PROTOCOLO DE COMUNICAÇÃO E PYTHON
while menu=="1" or menu=="2" or menu=="3":
menu=input("Escolha a opção desejada: "
"\n<1> - para Listar arquivos"
"\n<2> - para definir um diretório"
"\n<3> - para baixar um arquivo: ")
if menu=="1":
print(ftp.dir())
elif menu=="2":
ftp.cwd(input("Digite o diretório que deseja entrar: "))
print("\nDiretório corrente é: ", ftp.pwd())
elif menu=="3":
tipo=input("Digite <B> para arquivo binário ou "
"\nqualquer outra letra para arquivo ASCII: ").upper()
if tipo=="B":
with open(input("Digite o nome do arquivo destino: "), 'wb') as arq:
ftp.retrbinary('RETR ' + input("Arquivo de origem: "), arq.write)
else:
with open(input("Digite o nome do arquivo destino: "), 'w') as arq:
PROTOCOLO DE COMUNICAÇÃO E PYTHON
while menu=="1" or menu=="2" or menu=="3":
menu=input("Escolha a opção desejada: "
"\n<1> - para Listar arquivos"
"\n<2> - para definir um diretório"
"\n<3> - para baixar um arquivo: ")
if menu=="1":
print(ftp.dir())
elif menu=="2":
ftp.cwd(input("Digite o diretório que deseja entrar: "))
print("\nDiretório corrente é: ", ftp.pwd())
elif menu=="3":
tipo=input("Digite <B> para arquivo binário ou "
"\nqualquer outra letra para arquivo ASCII: ").upper()
if tipo=="B":
with open(input("Digite o nome do arquivo destino: "), 'wb') as arq:
ftp.retrbinary('RETR ' + input("Arquivo de origem: "), arq.write)
else:
with open(input("Digite o nome do arquivo destino: "), 'w') as arq:
PROTOCOLO DE COMUNICAÇÃO E PYTHON

Linhas 10, 11, 12, 13, 14 e 15: criamos uma variável “menu” para que o
usuário escolha uma das opções desejadas, enquanto o usuário digitar
algo igual a 1, 2 ou 3, o laço será repetido e o usuário perguntado
novamente sobre qual ação deseja realizar.
• Linhas 16 e 17: se o usuário digitar o número “1”, iremos exibir uma
listagem do diretório atual, exibindo arquivos e diretórios; após a exibição,
irá voltar para o menu.
• Linhas 18, 19 e 20: se o usuário digitar o número “2”, iremos mudar de
diretório de acordo com o que o usuário digitar. Seguindo o nosso
exemplo, digite: “seculoxx”, em seguida, será exibido o diretório atual e
voltará ao menu, utilize novamente a opção “1” para exibir o conteúdo do
diretório “seculoxx”.
• Linhas 21, 22 e 23: se o usuário digitar o número “3”, iremos perguntar o
que ele deseja baixar. Se for um arquivo binário, ele deverá digitar a letra
“b”. Qualquer outro caractere irá considerar o que ele deseja baixar como
ASCII. Seguindo o nosso exemplo, digite “B”.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Linhas 24, 25 e 26: nesse caso, se o usuário digitou “B”, iremos pedir o
nome do arquivo destino. Diante do nosso exemplo, digite “zipado.zip” (o
nome do arquivo deve ser completo, inclusive, com a extensão), em
seguida, ele pedirá o arquivo de origem; seguindo o nosso exemplo,
escolheremos o arquivo “representacao_politica.zip” (o nome do arquivo
deve ser completo, inclusive, com a extensão). Cuidado que o nome do
arquivo deve ser exatamente igual ao que está aparecendo na listagem.
Aguarde até surgir a mensagem “Arquivo baixado com sucesso” e, então,
aparecerá o menu novamente. Escolha a opção “3” para baixar um arquivo
e, na próxima pergunta, digite qualquer letra diferente de “B”, pois iremos
baixar um arquivo “ASCII”.
• Linhas 27 e 28: se o usuário digitar qualquer letra diferente de “B”,
representa que deseja baixar um arquivo “ASCII”. Ele solicitará o nome do
arquivo de destino; seguindo o nosso exemplo, digite: “textobaixado.txt”
(inclusive com a extensão).
• Linhas 29, 30 e 31: criamos a função para realizar a leitura das linhas e a
identificação do sistema operacional em relação ao separador de linha
utilizado dentro do arquivo.
PROTOCOLO DE COMUNICAÇÃO E PYTHON
Linha 32: irá solicitar o nome do arquivo de origem. Seguindo o nosso
exemplo, digite o arquivo “leia_me.txt”, exatamente igual. E então, o “arq”
será escrito com base no “leia_me.txt”.
• Linha 33: exibimos a mensagem de que o arquivo foi baixado (CUIDADO
com a tabulação dessa linha) e voltaremos para o menu.
• Linha 34: somente será executada se o usuário digitar algo diferente de
“1”, “2” ou “3”, o que encerrará a conexão.
Se você seguiu os nossos passos, durante a explicação das linhas, deverá
ter, no mesmo diretório do arquivo “FTP_Interativo.py”, os arquivos: “zipado.zip” e
“textobaixado.txt”. Nele, poderá exibi-los ou descompactá-los, no caso do arquivo
compactado. Assim, o seu usuário poderá interagir em qualquer servidor FTP,
navegar entre os diretórios e baixar arquivos ASCII ou binários.

Agora, imagine se pudermos criar uma interface a fim de sairmos do console,


o que acha? Legal, não é mesmo? Vamos desenvolver nossas interfaces, criar
ferramentas mais interativas e conectar nossas ferramentas a dispositivos IoT.
Aguarde... cenas do próximo capítulo!
Python & IOT

Primeiramente, é válido falar que todas as imagens aqui apresentadas, sobre


IoT, são imagens pautadas no Arduino, ou seja, se ainda não adquiriu um kit
Arduino, recomendo que o faça, para que possa praticar e criar soluções para
automação de tarefas do seu dia a dia, sem se preocupar com escalabilidade ou
com o negócio em si.
Sobre os Arduínos, vale relembrar que se trata de uma plataforma de
hardware para a rápida execução de projetos eletrônicos que, em conjunto com
vários sensores disponíveis no mercado, permite interagir com o meio. É um projeto
open source, tanto no que tange ao hardware quanto ao software, ou seja, caso
tenha conhecimentos em eletrônica, você mesmo pode desenvolver a sua placa de
Arduino. Pelo simples fato de ser open source, o seu custo é tão reduzido, assim
como os vários componentes que podemos conectar à placa, como sensores de
luminosidade, umidade, temperatura, leds, gases, sons e tantos outros.
Python & IOT

Caso ainda não tenha baixado o Arduino Sketch, utilize o link:


https://www.arduino.cc/en/Main/Software
void setup() => é executada apenas ao ligar o Arduino ou quando pressionamos o botão
“reset”;
e
void loop() => é executada sequencialmente infinitas vezes.
Python & IOT

As portas de entradas e saídas, tanto analógicas quanto digitais, servirão para


conectarmos os sensores e/ou atuadores, e as portas para alimentação serão utilizadas
para enviar energia para o funcionamento dos sensores e/ou atuadores.
Agora, que estabelecemos pontos importantes de conhecimentos sobre a IoT que iremos
utilizar, vamos começar a verificar como o Python entrará nesse cenário. Começaremos
pela biblioteca “serial”, que será a responsável por realizar a troca de dados entre o
Arduino e o Python por meio de uma comunicação que irá se estabelecer através de uma
porta serial. Caso você não tenha essa biblioteca instalada, abra o console (terminal) do
seu sistema operacional e digite:

Se for Windows:
pip install pyserial
Se for Linux:
apt-get install python-serial
Python & IOT
As portas de entradas e saídas, tanto analógicas quanto digitais, servirão para
conectarmos os sensores e/ou atuadores, e as portas para alimentação serão utilizadas
para enviar energia para o funcionamento dos sensores e/ou atuadores

Após concluir a instalação, vamos criar um novo “Directory” em nosso projeto


e, dentro dele, adicionar um “Python File”, chamado “Pacote_Serial.py”, no qual
será digitado o seguinte código (para Windows)

import serial
conexao = serial.Serial('COM3', 115200, timeout=0.5)

A partir do código apresentado, observamos a importação da biblioteca


“serial”, seguida da criação de um objeto, denominado “conexao”, que será
responsável por representar a saída serial (por meio do método “Serial()”) “COM3”,
sendo essa saída serial a que você está utilizando no Arduino Sketch.
Python & IOT

O segundo parâmetro do método “serial()” indica o “Baud Rate”, que está


associado à capacidade de transmissão de bits por segundo. O fator mais
importante sobre o “baud rate” é que os dispositivos conectados devem estar com a
mesma faixa de transmissão, ou seja, se você definir 9600 dentro do Python, o seu
Arduino deverá estar operando também na faixa de 9600; com valores diferentes,
dificilmente a transmissão de dados ocorrerá de maneira satisfatória. Para definição
dessa taxa, existem alguns valores padrões: 75, 300, 600, 1200, 2400, 4800, 9600,
19200, 28880, 38400, 57600 e 115200. O mais comumente utilizado é o 9600.

Quanto maior o valor, maior será a capacidade de transmissão, entretanto,


observe com cuidado dois pontos: quanto maior o valor, menor poderá ser a
distância entre os dispositivos interligados para que consigam realizar a transmissão
de modo satisfatório e, principalmente, se utilizar um valor muito alto, será que sua
aplicação conseguirá processar todos os dados que ela receberá? Por isso, defina
sempre dentro dos valores padrões e comuns, a não ser que tenha certeza de que o
valor utilizado atenda perfeitamente à sua solução.
Python & IOT

O último parâmetro refere-se ao tempo (em segundos) máximo que sua


aplicação irá esperar até recolher os dados enviados pelo dispositivo. Caso o
dispositivo envie os dados antes do tempo, sua aplicação irá recolhê-los. Se o
dispositivo não enviar os dados dentro do tempo definido, a sua aplicação irá
recolher os dados que já estiverem disponíveis. De acordo com o exemplo
apresentado, nossa aplicação irá recolher os dados a cada meio segundo, ou quando todos
os dados já estiverem prontos. Se você utiliza uma distribuição Linux,a segunda linha
deveria ser alterada para algo como:

conexao = serial.Serial('/dev/ttyUSB0', 115200)

Nesse caso, a principal mudança está relacionada à forma como o sistema


operacional identifica a porta serial, no Linux, as portas são identificadas por:
/dev/ttyUSB0, /dev/ttyUSB1 e assim sucessivamente. Já no Windows, as portas
seriais são identificadas por COM1, COM2 e assim sucessivamente.
Python & IOT

Se você executar o seu código, irá verificar uma mensagem de erro:


could not open port 'COM3'

O erro acima representa que a porta “COM3” não está disponível. Esse erro
somente não será apresentado para você, caso já esteja com o Arduino conectado
no seu computador e também se o Arduino estiver conectado na porta COM3. E
quando não sabemos exatamente em qual porta o nosso dispositivo está
conectado? Poderíamos abrir o Arduino Sketch e verificar atrás dele, mas essa ação
ficaria pouco prática. Podemos fazer isso dentro do nosso próprio código Python,
acrescentando as seguintes linhas:
Python & IOT

import serial
conexao=""
for porta in range(10):
try:
conexao = serial.Serial("COM"+str(porta), 115200, timeout=0.5)
print("Conectado na porta: ", conexao.portstr)
break
except serial.SerialException:
pass
if conexao!="":
conexao.close()
print("Conexão encerrada")
else:
print("Sem portas disponíveis")
Python & IOT

Esse código está próprio para Windows, caso utilize Linux deverá alterar a
linha:
• conexao = serial.Serial("COM"+str(porta), 115200,
timeout=0.5)
Por:
• conexao = serial.Serial("/dev/ttyUSB"+str(porta),
115200)

Com a execução do código, deverá ocorrer o seguinte resultado: se o seu


Arduino estiver devidamente conectado ao seu computador, deverá aparecer a porta
que está conectada e depois outra mensagem avisando que a conexão foi
encerrada. Por outro lado, caso não tenha nenhum Arduino conectado ao seu
computador, ele deverá exibir a mensagem “Sem portas disponíveis”.

Vamos explicar as linhas adicionadas:


Python & IOT

• Nas linhas 1 e 2: estamos importando a classe serial e criando uma variável “conexão” sem
qualquer conteúdo do tipo string.
• Na linha 3: abrimos um for que irá caracterizar um laço de repetição de 0 a 10. Esse
número irá representar a porta à qual o Arduino estará conectado. Se o seu Arduino estiver
na porta 11, ela não será encontrada por esse for, você deverá aumentar o número de
repetições do laço, entretanto, dificilmente seu dispositivo estará em uma porta serial
maior que 9.
• Na linha 4: abrimos um bloco “try”, que sempre virá acompanhado de um bloco “except”.
Dentro do “try”, colocamos as linhas que eventualmente podem disparar uma exceção. O
que é uma exceção? É um evento que o programador não consegue controlar, por
exemplo, não consigo controlar,quando esse código for executado, se o usuário irá ter
conectado o Arduino ou não. E, conforme fizemos anteriormente, no primeiro teste com
a saída serial, caso o Arduino não esteja conectado, será exibida uma mensagem de erro e
o programa será abortado. Não desejamos que isso ocorra, se a porta não estiver
disponível, quero que ele procure na próxima e assim sucessivamente, até a porta “9” e,
caso não encontre qualquer porta ativa, que simplesmente dê uma mensagem para o
usuário e não aborte o sistema
Python & IOT

•Por isso, colocamos as linhas 5, 6 e 7 dentro do “try”, indicando que, se houver qualquer
exceção, ou seja, se a linha 5 não conseguir estabelecer conexão com a saída serial, o
código irá pular para a linha “8”. Então, executará a linha “9” (que está dentro do bloco
except) e irá ignorar a exceção (comando “pass”), como consequência, não abortará
o sistema e permanecerá no laço executando o sistema normalmente.
• Linha 5: linha que tenta estabelecer a conexão com a porta serial, de acordo com o valor
que estiver valendo para o laço (valor da variável “porta” que irá variar entre 0 e 9). Se a
conexão for estabelecida com sucesso, passará para a linha 6, caso dê a exceção, ou seja,
se não conseguir conexão, irá direto para a linha 8 (bloco except), que executará
a linha 9 e, então, irá ignorar a exceção e continuar a execução do laço.
• Linha 6: somente será executada se a linha anterior ocorrer com sucesso, então, irá
mostrar para o usuário o nome da porta que conseguiu conectar, por meio do valor
“conexao.portstr”, que retorna a porta no formato string.
• Linha 7: irá abandonar o laço, uma vez que a conexão já foi estabelecida com sucesso.
• Linha 8: somente será executada se a conexão não for bem-sucedida e lançar uma
exceção do tipo “serial.SerialException”, ou seja, a conexão não ocorreu.
Standup da Equipe Indústrias
Willifred

Data: SEGUNDA TERÇA QUARTA QUINTA SEXTA


2 a 6 de junho de 2025

Realizações: Realizações: Realizações: Realizações: Realizações:


Tarefas: Tarefas: Tarefas: Tarefas: Tarefas:
Obstáculos: Obstáculos: Obstáculos: Obstáculos: Obstáculos:
TÁSSIA

Realizações: Realizações: Realizações: Realizações: Realizações:


Tarefas: Tarefas: Tarefas: Tarefas: Tarefas:
Obstáculos: Obstáculos: Obstáculos: Obstáculos: Obstáculos:
WALTER

Realizações: Realizações: Realizações: Realizações: Realizações:


Tarefas: Tarefas: Tarefas: Tarefas: Tarefas:
Obstáculos: Obstáculos: Obstáculos: Obstáculos: Obstáculos:
BRUNA

As reuniões colaborativas são as melhores! Clique em “Compartilhar”, adicione seus colegas e comece a interagir.
Python & IOT

Linha 9: esta linha faz com que o sistema não seja abortado, caso ocorra
a exceção “serial.SerialException”.

• Linhas 10, 11 e 12: se o conteúdo da variável não for vazio (significa que uma conexão
ocorreu com sucesso), irá fechar a conexão e exibir a mensagem “Conexao encerrada”.

• Linhas 13 e 14: caso contrário, ou seja, se nenhuma conexão foi realizada


com sucesso, irá exibir a mensagem “Sem portas disponíveis”.
Python & IOT

Enviando dados do Python para o Arduino

Vamos preparar um pequeno exemplo para entendermos como podemos


mandar dados do Python para um dispositivo Arduino. Vários seriam os exemplos a
ser explorados, como seu Python poderia monitorar um tráfego de dados em uma
rede e, caso o tráfego em uma estação saísse de um padrão, você enviaria um dado
para que um dispositivo Arduino disparasse uma sirene, por exemplo. Iremos fazer
com que o nosso código envie um sinal para ligar ou desligar um led. Começaremos
preparando o lado IoT.

Recebendo dados – Lado IoT

Separe uma protoboard, dois conectores macho (um verde e um branco), um


led, um resistor (marrom, laranja, laranja); na imagem a seguir, temos o resistor e o
led:
Python & IOT

Agora, seguiremos as seguintes etapas:


• Insira o led na protoboard;
• Na mesma fileira da perna maior do led, ligue uma das pontas do
resistor;
• Ligue a outra ponta do resistor em outra fileira vazia da protoboard e,
nessa mesma fileira, conecte uma das pontas do fio branco;
• A outra extremidade do fio branco irá na porta 10 do Arduino; e
Ligue o fio verde na fileira da perna menor do led, e a outra extremidade
do fio verde, você deverá ligar em uma porta GND do Arduino.
Você terá um cenário, como o apresentado pela imagem a seguir:
Python & IOT
Python & IOT

Agora que a estrutura está pronta, vamos desenvolver o código que o nosso
Arduino deverá receber, abra o “Arduino Sketch” e digite o código como apresentado
na imagem:
Python & IOT

Observando esse código, podemos notar que, na definição do “setup()”,


configuramos a porta 10 para um dispositivo somente de saída (output), no nosso
caso, o “led”. Também definimos a taxa de transmissão para “115200”, o mesmo
valor deverá ser determinado no nosso código do Python, para que possam ficar
sincronizados. Na função “loop()”, criamos uma variável para receber um valor
inteiro, chamada “valor_recebido”, e abrimos uma decisão que somente retornará
“True” (verdadeiro) se a saída serial estiver disponível para leitura.
Dentro da primeira tomada de decisão, recebemos o valor por meio da função
“read()”, que irá realizar a leitura do dado que estiver na saída serial. Depois,
verificaremos o valor que foi recebido. Se for igual a “0”, iremos passar para o nosso
dispositivo que está na porta 10 do Arduino (no nosso caso, o “led”) o valor “LOW”,
ou seja, iremos desligá-lo, caso contrário, iremos passar, para o mesmo dispositivo
que está na porta 10, o valor “HIGH”, isso significa que iremos ligá-lo. Em resumo,
“0” desliga e “1” liga o nosso led. Antes de passarmos para o nosso código em
Python, compile o seu código do Arduino, clicando sobre o botão destacado na
imagem a seguir:
Python & IOT
Python & IOT
Clicando sobre o botão em destaque nessa imagem, deverá aparecer, após a
compilação, uma mensagem como a que está na parte inferior da imagem. Caso
apareça uma mensagem com destaque em vermelho, significa que seu código
apresenta erro, procure corrigi-lo e clicar novamente, até que o código esteja
completamente correto, então, terá chegado o momento de passar o código para a
placa Arduino. Verifique se ela está devidamente conectada ao seu computador e
clique no botão que está em destaque na imagem a seguir:
Python & IOT

Enviando dados do Python para o Arduino

Vamos começar criando um novo arquivo do tipo “Python File”, chamado


“Enviar_Dados.py”. Digite os dados a seguir:

import serial
conexao=""
for porta in range(10):
try:
conexao = serial.Serial("COM"+str(porta), 115200, timeout=0.5)
print("Conectado na porta: ", conexao.portstr)
break
except serial.SerialException:
pass
Python & IOT

Enviando dados do Python para o Arduino

if conexao!="":
acao=input("Digite:\n<L> para Ligar\n<D> para Desligar: ").upper()
while acao=="L" or acao=="D":
if acao=="L":
conexao.write(b'1')
else:
conexao.write(b'0')
acao = input("Digite:\n<L> para Ligar\n<D> para Desligar: ").upper()
conexao.close()
print("Conexao encerrada")
else:
print("Sem portas disponíveis")
Python & IOT

Com base no código apresentado anteriormente, acrescentamos a esse novo


arquivo apenas as linhas que estão com a fonte em vermelho. Vamos à sua
explicação:
• Na primeira linha vermelha, criamos uma variável chamada “acao”, a qual
receberá as letras “L” ou “D” (convertendo o conteúdo digitado para letras
maiúsculas, por meio da função “upper()”), que representarão a ação de
ligar e desligar o led, respectivamente.
• Na segunda linha, iniciamos um laço de repetição que irá permanecer
perguntando ao usuário enquanto ele digitar “L” ou “D”, se ele digitar
qualquer outro caractere, o laço será encerrado.
• Dentro do laço, temos uma tomada de decisão composta, na qual estamos
avaliando, se o valor da variável “acao” for igual a “L”, iremos escrever na
porta serial (por meio da função “write()”), o caracter “1”. Perceba que
passaremos o dado no formato byte, pois, conforme vimos em capítulos
anteriores, o formato de bytes é o utilizado para a transmissão de dados
via protocolos de transporte. Caso contrário, o dado enviado para a saída
serial será “0”.
Python & IOT

• Fora da tomada de decisão, será perguntado ao usuário o que deseja


realizar, lembrando que, se digitar algo diferente de “L” ou “D”, o laço será
encerrado, a conexão fechada e exibirá a mensagem “Conexão
encerrada.”.
Dessa forma, com o dispositivo devidamente conectado ao seu computador,
rode sua aplicação Python e verificará que quando digitar “L”, o led irá acender, e
quando digitar “D”, o led irá apagar. Você pode procurar adicionar mais leds à sua
protoboard, a fim de treinar um pouco mais, sendo um vermelho, um amarelo e um
verde. Conforme o valor recebido, ele irá acender apenas um dos três leds, como se
fosse um semáforo, por exemplo, se enviar “1”, o semáforo será fechado; se enviar
“2”, acenderá o amarelo; e se enviar o “3”, o semáforo será aberto. Procure praticar
e dar asas à sua imaginação.
Python & IOT

Enviando dados do Arduino para o Python

Agora, montaremos outro exemplo, no qual realizaremos o processo inverso.


Iremos definir a mudança no dispositivo, no nosso caso, o led, e os dados serão
enviados para o Python. Vamos lá!

Enviando dados – Lado IoT

Utilizaremos a mesma estrutura apresentada anteriormente, mas, dessa vez,


o Arduino irá ligar e desligar o “led” por meio de um intervalo de tempo e o Python irá
receber o estado do led, ou seja, será informado se ele está ligado ou desligado.
Mudaremos o nosso código no Arduino Sketch para:
Python & IOT

void setup()
{
pinMode(10, OUTPUT);
Serial.begin(115200);
}
void loop() {
int intervalo_pisca;
intervalo_pisca=4000;
digitalWrite(10, LOW);
Serial.write('0');
delay(intervalo_pisca);
digitalWrite(10, HIGH);
Serial.write('1');
delay(intervalo_pisca);
}
Python & IOT

Com base no código apresentado, primeiramente definimos a função


“setup()”, assim como no tópico anterior, mas dentro da função “loop()”, o código foi
alterado significativamente. Vejamos:

Nas duas primeiras linhas, criamos uma variável para controlar o intervalo
de tempo entre ligar e desligar o led. A unidade de medida utilizada é em
milissegundos, por isso, com 4000 estamos representando de quatro em
quatro segundos.
• Na terceira linha, desligamos o nosso led.
• Na quarta linha, escrevemos na porta serial o valor “0”, por meio da função
“write()”.
• Na quinta linha, chamamos a função “delay()” e passamos para ela o valor
dado ao intervalo que está dentro da variável “intervalo_pisca”.
• Nas três últimas linhas, ligamos o led, escrevemos na saída serial o valor
“1” e ativamos a espera.
Verifique se digitou tudo corretamente e transfira para o seu Arduino
Python & IOT

Recebendo dados – Lado Python

Crie um novo arquivo do tipo “Python File”, com o nome


“Receber_Dados.py”, e digite o código a seguir:

import serial
conexao=""
for porta in range(10):
try:
conexao = serial.Serial("COM"+str(porta), 115200)
print("Conectado na porta: ", conexao.portstr)
break
except serial.SerialException:
pass
Python & IOT

if conexao!="":
while True:
resposta = conexao.read()
if resposta==b'1':
print("LED Ligado")
else:
print("LED Desligado")
conexao.close()
print("Conexão encerrada")
else:
print("Sem portas disponíveis")
Python & IOT

As linhas destacadas na cor vermelha foram as linhas alteradas de acordo


com o primeiro código, no qual estabelecemos a primeira conexão com o Arduino.
Vejamos as linhas inseridas, com mais detalhes:
• Na primeira linha, na qual definimos o objeto de conexão, retiramos o
parâmetro “timeout”. Isso porque a função do código será receber o valor,
bastando que o valor esteja disponível na porta serial para que o código
realize a leitura, não precisamos de qualquer intervalo de tempo.
• Já dentro da tomada de decisão para a conexão válida, criamos um laço
infinito, que receberá o dado da porta serial por meio do método “read()” e
armazenará na variável “resposta”. Sempre é bom relembrar que o dado
recebido estará no formato “byte”.
Python & IOT

Finalizamos com uma tomada de decisão: se o valor recebido for igual a


“1”, iremos exibir a mensagem “LED Ligado”, caso contrário, “LED
Desligado”.
Dessa forma, conecte o seu Arduino, caso não tenha realizado a transferência
do novo código, faça-a nesse momento e execute o seu código Python. Você verá
que, quando o led acender, o Python irá receber o valor e imprimir a mensagem de
que o led está “ligado”. Quando receber o valor “0”, irá imprimir a mensagem de que
o led foi “desligado” e assim ficará, infinitamente, até que você interrompa o
processo.
Python & IOT

Persistindo os dados recolhidos

Agora, vamos montar mais um exemplo no qual a nossa aplicação Python irá
receber os dados e gravá-los fisicamente em um arquivo “json”. Para isso, vamos
utilizar um sensor de luminosidade LDR (Light Dependent Resistor) que funciona
variando sua resistência elétrica por meio da luminosidade recebida. Isso significa
que quanto mais luz, menor a resistência elétrica e vice-versa. Precisaremos, para o
desenvolvimento desse exemplo, de: um sensor de luminosidade LDR, uma
protoboard, um resistor (marrom, preto, laranja), três cabos machos e a nossa placa
Arduino.

Sensor de Luminosidade LDR


Protoboard
Cabos Jumper Machos
Resistores preto marrom laranja
Python & IOT

A montagem deve seguir as instruções a seguir:


• Encaixe o sensor de luminosidade na protoboard, na mesma fileira de
uma das pernas do sensor, ligue uma ponta de um cabo vermelho; e a
outra extremidade desse cabo, ligue na porta de 5V do Arduino.

Na fileira da outra perna do sensor, encaixe um cabo verde, a outra


extremidade do cabo verde, você deverá encaixar em uma porta
analógica do Arduino, utilizaremos a porta “A1”. Ainda nessa fileira da
protoboard, encaixe uma das extremidades do resistor à outra perna do
resistor e deixe em uma fileira livre da protoboard.
• Na fileira onde está somente a perna do resistor, conecte um cabo preto,
e a outra extremidade desse cabo, conecte em uma porta “GND” da
placa Arduino.

Agora que a ligação está pronta, conecte a sua placa Arduino ao seu
computador e, no Arduino Sketch, digite o seguinte código:
Python & IOT

void setup() {
Serial.begin(115200);
}
void loop() {
int luz=analogRead(1);
Serial.println(luz);
delay(5000);
}

Podemos observar, nesse código, que definimos a taxa de transmissão para


115200 e, na função “loop()”, criamos uma variável chamada de “luz”, que irá
receber os dados capturados pelo sensor (por meio do método “analogRead()”)
conectado na porta “A1”. Caso você tenha utilizado outra porta analógica, terá
também que mudar o valor da função “analogRead()”. Caso tenha conectado na
porta “A2”, terá que colocar o número “2” dentro dos parênteses da função
“analogRead()”.
Python & IOT

Em seguida, iremos transmitir para a saída Serial o valor que foi retornado
pelo sensor. Detalhe para a utilização do método “println()” e não o “write()”, devido
ao retorno do dado ser dinâmico em relação ao seu tamanho, ou seja, não
conseguimos precisar a quantidade de caracteres que será retornada pelo sensor.
Assim, utilizaremos “println()”, que é um método mais flexível, e, por fim,
acrescentaremos um tempo de 5 segundos para a próxima captura. Compile e, em
caso de sucesso, transmita o código para a sua placa Arduino.

Agora, vamos para o PyCharm. Crie um novo arquivo do tipo “Python File”,
denominado “Capturar_Temperatura.py”, no qual irá digitar o seguinte código
Python & IOT

import serial
conexao=""
for porta in range(10):
try:
conexao = serial.Serial("COM"+str(porta), 115200)
print("Conectado na porta: ", conexao.portstr)
break
except serial.SerialException:
pass
if conexao!="":
while True:
resposta = conexao.readline()
print(resposta.decode())
conexao.close()
print("Conexão encerrada")
else:
print("Sem portas disponíveis")
Python & IOT

Observe as funções das linhas com mais detalhes:


• Linhas 1 e 2: importamos a biblioteca e criamos uma variável para receber a conexão.
Linha 3 a 9: montamos um laço para que o programa procure a porta na
qual o Arduino está conectado.
• Linhas 10 e 11: se a conexão estiver diferente de vazio, ou seja, se a conexão foi
estabelecida, então, teremos um laço infinito.
• Linha 12: dentro do laço, armazenaremos a resposta por meio do método “readline()”.
Repare que, dessa vez, não utilizamos o método “read()”,porque será informada uma
quantidade de dados indeterminada e podemser retornados um caractere, dois caracteres
e assim sucessivamente.
• Linha 13: imprimimos o valor capturado pela variável “resposta”,convertendo o seu
conteúdo de “byte” para “string”, por meio da função “decode()”, conforme já vimos
anteriormente. Em seguida, as linhas são responsáveis por encerrar a conexão ou avisar
ao usuário que não foi possível realizar a conexão. Isso normalmente ocorre quando a
porta já está em uso, ou seja, caso tente executar o código duas vezes simultaneamente,
você verá uma mensagem de erro falando que a porta já está em uso, portas seriais
suportam apenas uma conexão.
Python & IOT

Agora, basta executar a sua aplicação Python. Você verá algum número
provavelmente entre “100 e 999”, quanto menor, menos luminosidade, e vice-versa.
Procure colocar o seu dedo sobre o sensor e observe a alteração do valor que será
exibida. Procure também posicionar a lanterna do celular sobre o sensor e verá que
o número irá aumentar. Agora, iremos realizar uma pequena alteração para que
possamos armazenar os dados em um arquivo, posteriormente. Poderíamos utilizá-
los para realizar médias, montar relatórios com histórico, entre tantas outras ações
com esses dados. Dentro do código anterior, realize as seguintes alterações:

import serial
import json
import time
from datetime import datetime
conexao=""
for porta in range(10):
try:
conexao = serial.Serial("COM"+str(porta), 115200)
print("Conectado na porta: ", conexao.portstr)
Python & IOT

if conexao!="":
dicionario={}
cont=0
while cont<10:
resposta=conexao.readline()
dicionario[str(datetime.now())]=[resposta.decode('utf-8')[0:3]]
print(resposta.decode('utf-8')[0:3])
cont+=1
with open('Temperatura.json', "w") as arq:
json.dump(dicionario, arq)
conexao.close()
print("Conexão encerrada")
else:
print("Sem portas disponíveis")
Python & IOT

if conexao!="":
dicionario={}
cont=0
while cont<10:
resposta=conexao.readline()
dicionario[str(datetime.now())]=[resposta.decode('utf-8')[0:3]]
print(resposta.decode('utf-8')[0:3])
cont+=1
with open('Temperatura.json', "w") as arq:
json.dump(dicionario, arq)
conexao.close()
print("Conexão encerrada")
else:
print("Sem portas disponíveis")
Python & IOT

Avaliando as linhas do nosso código acima:


• Linhas 1, 2 e 3: realizamos os imports das bibliotecas serial (para
recuperar os dados do Arduino), json (para permitir a gravação dos dados)
e datetime (para que possamos retornar a data e/ou hora do sistema).
• Linha 4: criamos um objeto para receber a conexão com o Arduino.
• Entre as linhas 5 e 11: montamos o for para buscar a porta disponível
para a conexão.
• Linha 12: a tomada de decisão, caso a conexão seja estabelecida com
sucesso ou, se não houver conexão, será exibida a mensagem “Sem
portas disponíveis”.
• Linhas 13 e 14: criamos um dicionário para armazenar os dados e depois
serem persistidos no arquivo “.json”.
• Linha 15: iniciamos um laço que irá repetir o código por dez vezes, o laço
será controlado por meio da variável “cont”.
• Linha 16: retorna o dado que está na porta “serial” e armazenaremos na
variável “resposta”
Python & IOT

Linha 17: iremos adicionar no “dicionario” um novo elemento que terá


como chave a data e hora (“now()” retorna, data e hora com
milissegundos) e o valor será o dado retornado por meio da porta serial,
decodificado para string e consideraremos apenas os três primeiros
caracteres ([0:3]), que representam efetivamente o nível de luminosidade.
Por exemplo: {"2018-06-16 20:33:14.022459": ["958"]}.

Linha 18: estamos exibindo apenas o dado que será persistido no


dicionário como valor.
• Linha 19: adicionamos mais uma na variável “cont”.
• Linhas 20 e 21: estamos definindo que o nome do arquivo será
“Temperatura.json” em modo de escrita (“w”), e que, dentro do “with”, o
arquivo será representado pela palavra “arq”. Dentro do “with”, invocamos
o método “dump()” para realizarmos a gravação do arquivo json.
Python & IOT

Finalizamos o código após a gravação.

Quando executar o código, e o laço “while” for concluído, um arquivo “json”


será criado. A partir dele, muitas ações poderão ser utilizadas, como armazenar um
banco de dados, realizar uma análise sobre os dados, determinar médias, enfim,
uma infinidade de possibilidades.

Agora, cabe a você, com toda a sua criatividade, utilizar diversos sensores
para que possa desenvolver soluções aplicadas para a sua área de atuação
profissional. Por exemplo, você pode desenvolver uma solução que ficará
responsável por verificar a resposta de um IP responsável por algum serviço dentro
da rede, e assim que ele não responder, o seu componente IoT pode disparar uma
sirene, gerar um log, piscar uma luz ou passar um sinal para um aplicativo no
smartphone ou qualquer outra forma de aviso de que o serviço saiu do ar.

Você também pode gostar