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 o conteúdo inteiro de um arquivo var_arquivo
já aberto para leitura, podemos usar a função var_arquivo.read()
, que devolve uma string (str
).
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.txt', lê cada linha do arquivo e a imprime.
nome_do_arquivo = "meu_arquivo.txt"
arquivo = open(nome_do_arquivo, 'r') # abre o arquivo para leitura
print("Conteúdo do arquivo '%s'\n" %nome_do_arquivo)
conteudo = arquivo.read() # lê o conteúdo do arquivo
print(conteudo)
arquivo.close() # depois do uso, fecha o arquivo
Quando o arquivo é muito grande, ler o seu conteúdo inteiro de uma só vez não é uma boa ideia, pois ele pode ocupar toda a memória do computador. Nesse caso, o melhor é ler uma linha do arquivo por vez.
Para ler uma linha de um arquivo var_arquivo
já aberto para leitura, podemos usar a função var_arquivo.readline()
, que também devolve uma string (str
). Quando se está no final do arquivo, a função readline()
devolve uma string vazia (''
).
nome_do_arquivo = "meu_arquivo.txt"
arquivo = open(nome_do_arquivo, 'r') # abre o arquivo para leitura
print("Conteúdo do arquivo '%s'\n" %nome_do_arquivo)
linha = arquivo.readline() # lê uma linha do arquivo
while linha != "": # enquanto não chegou ao final do arquivo
print(linha,end="") # imprime a linha
linha = arquivo.readline() # lê uma nova linha do arquivo
arquivo.close() # depois do uso, fecha o arquivo
Para fazer um laço que lê todas as linhas de um arquivo (uma por vez), também 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, como ilustrado abaixo:
nome_do_arquivo = "meu_arquivo.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 a 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'
. O exemplo abaixo lê o arquivo 'meu_arquivo_latin1.txt', que tem codificação latin1
.
nome_do_arquivo = "meu_arquivo_latin1.txt"
arquivo = open(nome_do_arquivo, 'r', encoding="latin1") # 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 a linha
arquivo.close() # depois do uso, fecha o arquivo
É possível evitar de ter que fechar explicitamente um arquivo (com close()
) usando o comando with (...) as <nome_var> :
na sua abertura, como no exemplo abaixo. Ao final do corpo do with
, o comando with
fecha automaticamente o arquivo.
nome_do_arquivo = "meu_arquivo.txt"
with open(nome_do_arquivo, 'r') as arquivo: # abre o arquivo para leitura
# Corpo do WITH
print("Conteúdo do arquivo '%s'\n" %nome_do_arquivo)
for linha in arquivo: # percorre cada linha do arquivo
print(linha,end="") # imprime a linha
print("Fim!")
Importante: Para poder reler a partir da primeira linha um arquivo que está aberto e já foi lido, é preciso reabri-lo com a função open()
. Todo arquivo aberto tem um marcador que indica a posição do primeiro caracter que ainda não foi lido do arquivo (ou seja, a posição de início da próxima leitura a ser realizada). A função open()
põe o marcador no início do arquivo. E a cada vez que chamamos a função read()
ou a função readline()
, o marcador se move para o caractere que vem em seguida do último caractere retornado. No caso de readline
, o marcador se move para o primeiro caractere da próxima linha. No caso de read
, o marcador se move para o final do arquivo.
Também podemos usar a função open()
para criar um arquivo para a gravação de dados, passando como parâmetros para ela o nome (com caminho, se necessário) do arquivo a ser criado e a string 'w' (de write
, para indicar que o arquivo será aberto para escrita).
Para gravar uma string em um arquivo var_arquivo
já aberto para escrita, podemos usar a função var_arquivo.write()
.
Assim como na leitura de arquivos, depois que o uso de um arquivo aberto para escrita já tiver sido encerrado, é preciso fechar o arquivo por meio da função close()
.
Veja o exemplo a seguir, que cria um arquivo chamado 'meu_poema.txt'
e grava um poema nele.
nome_do_arquivo = "meu_poema.txt"
arquivo = open(nome_do_arquivo, 'w') # Cria ou abre o arquivo para escrita
poeminha = ["Batatinha quando nasce","Espalha a rama pelo chão","Menininha quando dorme"]
for linha in poeminha:
arquivo.write(linha) # grava uma linha do poema no arquivo
arquivo.write('\n') # coloca uma quebra de linha no final da linha do poema
arquivo.close() # depois do uso, fecha o arquivo
Quando abrimos um arquivo com a opção de escrita 'w'
, se o arquivo não existe previamente, ele será criado pela função open()
. Entretanto, caso o arquivo já exista, o seu conteúdo atual será sobreescrito (ou seja, perdido).
Para acrescentarmos conteúdo no final de um arquivo que já existe, podemos abrir o arquivo com 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 'a' (de append
, para indicar que o arquivo será aberto para escrita preservando o seu conteúdo atual). Caso o arquivo que se tenta abrir com opção 'a'
não existe previamente, ele será criado pela função open().
Para gravar uma string no final de um arquivo aberto com a opção 'a'
, também usamos a função write()
.
Veja o exemplo a seguir, que adiciona novas frases ao final do arquivo chamado 'meu_poema.txt'
:
nome_do_arquivo = "meu_poema.txt"
arquivo = open(nome_do_arquivo, 'a') # Abre o arquivo para append (acréscimo)
fim_poeminha = "Põe a mão no coração"
arquivo.write(fim_poeminha)
arquivo.close() # depois do uso, fecha o arquivo
Quando tentamos usar a função open()
para abrir para leitura um arquivo que não existe ou passamos um caminho inválido para um arquivo a ser aberto, 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')
O programa abaixo pede que o usuário digite o nome de um 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), o programa pede para que o usuário digite novamente um nome de arquivo e tenta abri-lo novamente. O programa repete essas operações até que o usuário digite o nome de um arquivo que exista.
# 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
Para evitar que a execução do programa seja interrompida quando o erro FileNotFoundError
acontece, o programa usa o comando para tratamento de exceções try
.
O Python começa tentando executar o bloco de comandos associado à cláusula try
e caso tudo corra bem (no exemplo acima, 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 FileNotFoundError
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 a seguinte referência:
... consulte a seguinte referência:
Escreva um programa que lê um arquivo e o imprime com as linhas numeradas.
def main():
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
arquivo.close()
main()
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.
def main():
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
arquivo.close()
main()
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()
.
def main():
nome_do_arquivo = input("Nome do arquivo: ")
arquivo = open(nome_do_arquivo, 'r', encoding='utf8')
nlin = 1
for linha in arquivo:
linha = linha.rstrip()
print('%4d: %s' %(nlin,linha))
nlin += 1
arquivo.close()
main()
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 19.1: 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.
def main():
abriu = False
while not abriu:
nome_do_arquivo = input("Digite o nome do arquivo de dados: ")
try:
arquivo = open(nome_do_arquivo, 'r', encoding = 'utf8')
except FileNotFoundError:
print(nome_do_arquivo, " não encontrado. Você digitou direito?")
else:
abriu = True
nlin = 1
for linha in arquivo:
linha = linha.rstrip()
print('%4d: %s' %(nlin,linha))
nlin += 1
arquivo.close()
main()
Escreva um programa que leia um arquivo onde cada linha contém o nome e as notas de um estudante e, para cada estudante, calcule e imprima a média das notas. Ao final, o programa deve imprimir também a média da turma.
Exemplo: para o arquivo notas.txt
com:
jose 10 15 20 30 40
pedro 23 16 19 22
suzana 8 22 17 14 32 17 24 21 2 9 11 17
gisela 12 28 21 45 26 10
joao 14 32 25 16 89
a saída deve ser:
Digite o nome do arquivo: notas.txt
Aluno: jose Média = 23.000000
Aluno: pedro Média = 20.000000
Aluno: suzana Média = 16.166667
Aluno: gisela Média = 23.666667
Aluno: joao Média = 35.200000
Média da turma = 23.606667
def main():
nome = input("Digite o nome do arquivo: ")
try:
arquivo = open(nome, 'r') # abre o arquivo para leitura
except:
print("Não consegui abrir o arquivo %s" %(nome))
else:
total = 0
cont_alunos = 0
for linha in arquivo:
dados = linha.split()
notas = dados[1:]
soma = 0
for n in notas:
soma += float(n)
media = soma/len(notas)
print("Aluno: %s \t Média = %f"%(dados[0],media))
total += media
cont_alunos += 1
print("Média da turma = %f"%(total/cont_alunos))
arquivo.close() # fecha o arquivo
main()
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())
try