Nos exercícios que fizemos no curso até a aula de hoje, sempre criamos programas que manipulavam dados digitados pelos usuários. Entretanto, essa não é a unica forma de entrada de dados que podemos usar em um programa. Uma outra forma de entrada de dados usada com frequência em programas é a leitura de dados gravados em um arquivo.
Para abrir um arquivo para leitura, podemos usar a função open()
, passando como parâmetros para ela o nome (com caminho, se necessário) do arquivo a ser aberto e a string 'r'
(de read
, para indicar que o arquivo será aberto para leitura). A função devolve um objeto do tipo file
.
Para ler as linhas de um arquivo já aberto, podemos usar o comando for var_linha in arquivo:
, onde var_linha
é o nome da variável que armazenará o conteúdo de uma linha e var_arquivo
é o arquivo já aberto para leitura. Depois que o uso de um arquivo já tiver sido encerrado, é preciso fechar o arquivo por meio da função close()
.
Veja o exemplo a seguir, que abre um arquivo chamado 'meu_arquivo_utf8.txt', lê cada linha do arquivo e a imprime.
nome_do_arquivo = "meu_arquivo_utf8.txt"
arquivo = open(nome_do_arquivo, 'r', encoding="utf8") # abre o arquivo para leitura
print("Conteúdo do arquivo '%s'\n" %nome_do_arquivo)
for linha in arquivo: # percorre cada linha do arquivo
print(linha,end="") # imprime uma linha
arquivo.close() # depois do uso, fecha o arquivo
No exemplo acima, passamos um terceiro parâmetro para a função open()
, o parâmetro chamado encoding
. Esse parâmetro é opcional; quando não passamos nenhum valor para ele, o valor usado é a codificação padrão do Python 3, que é 'utf8'
. Um outro valor possível para o parâmetro encoding
é o 'latin1'
.
Quando tentamos abrir para leitura um arquivo que não existe, a função gera o erro FileNotFoundError
, como mostrado abaixo:
nome_do_arquivo = "bla_bla.txt" # nome que não corresponde a um arquivo existente
arquivo = open(nome_do_arquivo, 'r')
No "esqueleto" do EP3, há um exemplo de leitura de arquivo, na função leitura_dos_dados()
, que lê um arquivo contendo medições metereológicas e gera uma tabela (matriz) contendo os dados lidos do arquivo. A função pede que o usuário digite o nome do arquivo a ser aberto, mas caso o usuário digite um nome de arquivo que não existe, em vez da execução da função ser interrompida pelo erro FileNotFound
(gerado pela tentativa de abertura do arquivo), a função pede para que o usuário digite novamente um nome de arquivo e tenta abri-lo novamente. A função repete essas operações até que o usuário digite o nome de arquivo que exista.
Mas como a função leitura_dos_dados()
dos dados é capaz de fazer isso? Mais especificamente, como ela evita que a execução do programa seja interrompida quando o erro FileNotFound
acontece?
Ela faz isso por meio do comando para tratamento de exceções try
. Veja um exemplo de uso do try
a seguir:
# Lê o nome do arquivo de dados e o abre para leitura
abriu = False
while not abriu:
nome_do_arquivo = input("Digite o nome do arquivo de dados: ")
try:
arquivo = open(nome_do_arquivo, 'r')
except FileNotFoundError:
print(nome_do_arquivo, " não encontrado. Você digitou direito?")
else:
abriu = True
print("Conteúdo do arquivo '%s'\n" %nome_do_arquivo)
for linha in arquivo:
print(linha,end="")
arquivo.close() # depois do uso, fecha o arquivo
O Python começa tentando executar o bloco de comandos associado à cláusula try
e caso tudo corra bem (no exemplo, se o arquivo existe e foi aberto para leitura com sucesso), então pula o bloco de comandos associado à cláusula except
e executa o bloco de comandos associado à cláusula else
. Mas se o erro FileNotFound
ocorrer durante a execução dos comandos no try
, então o bloco de comandos associado à cláusula except
é executado e depois o bloco de comandos do else
é pulado.
A cláusula else
é opcional. Portanto, podemos ter um comando try
só com except
. Além disso, no except
podemos não especificar o tipo de erro que se deseja capturar. Nesse caso, qualquer erro que for gerado durante a execução dos comandos no bloco do try
causará a execução dos comandos no bloco do except
. Veja outro exemplo a seguir:
divisor = 0
try:
print("Agora eu vou dividir...")
divisao = 100 / divisor
print("Resultado da divisão:", divisao )
except:
print("Não consegui calcular a divisão!")
... consulte as seguintes referências:
... consulte a seguinte referência:
Escreva um programa que lê um arquivo e o imprime com as linhas numeradas.
nome_do_arquivo = input("Nome do arquivo: ")
arquivo = open(nome_do_arquivo, 'r', encoding='utf8')
nlin = 1
for linha in arquivo:
print(nlin, ':', linha)
nlin += 1
A impressão gerada pela solução acima não ficou muito boa. As linhas estão separadas por uma linha em branco e os números não ficaram alinhados.
O problema das linhas em branco acontece porque quando lemos cada linha do arquivo, ela já vem com uma quebra de linha no final. E quando usamos o comando print
exibir a linha, ele inclui uma outra quebra de linha. Então, para resolver o problema, podemos usar o print
passando para ele o parâmetro end=''
, como mostrado na Solução 2.
nome_do_arquivo = input("Nome do arquivo: ")
arquivo = open(nome_do_arquivo, 'r', encoding='utf8')
nlin = 1
for linha in arquivo:
print('%4d: %s' %(nlin,linha), end="")
nlin += 1
Agora a impressão ficou correta. :)
Mas temos ainda uma terceira alternativa de solução, que elimina a quebra de linha do final de uma linha lida do arquivo. Essa solução envolve o uso da função rstrip()
.
nome_do_arquivo = input("Nome do arquivo: ")
arquivo = open(nome_do_arquivo, 'r', encoding='utf8')
nlin = 1
for linha in arquivo:
linha = linha.rstrip() # elimina
print('%4d: %s' %(nlin,linha))
nlin += 1
A chamada S.rstrip()
que devolve uma cópia da string S sem os "caracteres brancos" que ela tiver em seu final. São considerados caracteres brancos os caracteres espaço (' '
), tabulação (\t
) e quebra de linha (\n
).
Temos também as funções lstrip()
(que devolve uma cópia da string eliminando todos os caracteres brancos do início da string) e lstrip()
(que devolve uma cópia da string eliminando todos os caracteres brancos do início e do fim da string). Veja os exemplos abaixo:
texto = "\n\n \t Pequeno texto de teste! \t\t \n\n"
print(texto)
print("--------------")
print(texto.rstrip())
print("--------------")
print(texto.lstrip())
print("--------------")
print(texto.strip())
print("--------------")
Mas agora, voltando ao problema 26: e se o nome de arquivo digitado pelo usuário não corresponde a um arquivo que existe? Seria interessante avisar o usuário sobre o problema e permitir que ela escolha um outro arquivo. A Solução 4 faz isso.
abriu = False
while not abriu:
nome_do_arquivo = input("Digite o nome do arquivo de dados: ")
try:
arquivo = open(nome_do_arquivo, 'r')
except FileNotFoundError:
print(nome_do_arquivo, " não encontrado. Você digitou direito?")
else:
abriu = True
nlin = 1
for linha in arquivo:
print('%4d: %s' %(nlin,linha), end="")
nlin += 1
Exemplo: para o texto: ",1,,2,3,"
e a vírgula como separador, a saída deve ser a lista:
['', '1', '', '2', '3', '']
onde ''
indica uma palavra vazia (entre 2 separadores consecutivos).
def separa(texto, sep):
lista = []
palavra = ''
for l in texto:
if l == sep:
lista.append(palavra)
palavra = ''
else:
palavra += l
lista.append(palavra)
return lista
frase = input("Digite palavras separadas por vírgula: ")
palavras = separa(frase, ',')
print (palavras)
if len(palavras) > 0:
maxp = palavras[0]
for p in palavras:
print ("A palavra '%s' tem %d caracteres."%(p, len(p)))
if len(p) > len(maxp):
maxp = p
print("A maior palavra é '%s', que tem %d caracteres."%(maxp, len(maxp)))
else:
print("Não achei nenhuma palavra em sua frase!")
split()
frase = input("Digite palavras separadas por vírgula: ")
palavras = frase.split(',')
print (palavras)
if len(palavras) > 0:
maxp = palavras[0]
for p in palavras:
print ("A palavra '%s' tem %d caracteres."%(p, len(p)))
if len(p) > len(maxp):
maxp = p
print("A maior palavra é '%s', que tem %d caracteres."%(maxp, len(maxp)))
else:
print("Não achei nenhuma palavra em sua frase!")
Obs.: Quando fazemos uma chamada do tipo S.split()
, ou seja, chamamos a split
a partir de uma string S
sem passar para a função nenhum separador, a função separará S
nos caracteres brancos (espaços, tabulações e quebras de linhas); além disso, as strings vazias são removidas da lista de resultado. Veja os exemplos abaixo:
texto = "Para ser grande,\t sê inteiro:\tnada\nTeu exagera ou exclui."
print(texto)
print("----------")
print("Separando pelo caracter de espaço: ", texto.split(" "))
print("Separando pelo caracter de tabulação: ", texto.split("\t"))
print("Separando pelos caracteres brancos: ", texto.split())
Escreva um programa que lê vários números reais em uma mesma linha e imprime a soma.
texto = input("Números: ")
numeros = texto.split()
soma = 0
for n in numeros:
soma += float(n)
print("Soma = %f" %(soma))
Escreva um programa que leia um arquivo contendo ao menos 1 número real por linha, e para cada linha imprima a sua soma. Ao final, o programa deve imprimir também a soma total.
Exemplo: para o arquivo numeros.txt
com:
5 4 3 2 1 4 4 4 2.7 3.14 2.1
a saída deve ser:
Digite o nome do arquivo: numeros.txt Soma = 15.000000 Soma = 12.000000 Soma = 2.700000 Soma = 5.240000 Total = 34.940000
import sys
nome = input("Digite o nome do arquivo: ")
try:
arquivo = open(nome, 'r') # abre o arquivo para leitura
except IOError:
print("Não consegui abrir o arquivo %s" %(nome))
sys.exit(0) # Encerra a execução do programa
total = 0
for linha in arquivo:
numeros = linha.split()
soma = 0
for n in numeros:
soma += float(n)
print("Soma = %f"%(soma))
total += soma
print("Total = %f"%(total))
arquivo.close() # fecha o arquivo
try
strip()
e split()
Working with Files, no site Think Python - How to Think Like a Computer Scientist (versão interativa) >> http://interactivepython.org/courselib/static/thinkcspy/Files/files.html
Capítulo 8 - Errors and Exceptions, do tutorial do Python 3 >> https://docs.python.org/3/tutorial/errors.html
Projeto MacMulti - Listas de exercícios (Introdução à Computação) >> http://www.ime.usp.br/~macmulti/exercicios/