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
trystrip() 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/