Artigo original: Python Write to File – Open, Read, Append, and Other File Handling Functions Explained

Boas-vindas

Olá! Se você deseja aprender como escrever em arquivos em Python, este artigo é para você. Trabalhar com arquivos é uma habilidade importante que todo desenvolvedor em Python deve aprender.

Neste artigo, você saberá:

  • Como abrir um arquivo.
  • Como ler um arquivo.
  • Como criar um arquivo.
  • Como modificar um arquivo.
  • Como fechar um arquivo.
  • Como abrir arquivos para várias operações.
  • Como trabalhar com métodos de objetos de arquivo.
  • Como excluir arquivos.
  • Como trabalhar com gerenciadores de contexto e porquê eles são úteis.
  • Como lidar com exceções que podem surgir enquanto trabalha com seus arquivos
  • e mais!

Vamos começar! ✨

🔹 Trabalhando com arquivos: sintaxe básica

Uma das funções mais importantes que você precisará usar enquanto trabalha com arquivos em python é open(), uma função interna que abre arquivos e permite que seus programas os utilizem e trabalhem com eles.

Esta é a sintaxe básica:

image-48
Na caixa laranja: "Caminho relativo ou absoluto para o arquivo (incluindo a extensão." | Na caixa verde: "Uma string (caractere) que indica o que você quer fazer com o arquivo."

💡 Dica: estes são os dois argumentos mais comumente utilizados para chamar esta função. Existem mais seis opções de argumentos. Para aprender mais sobre eles, leia este artigo da documentação.

Primeiro parâmetro: o arquivo

O primeiro parâmetro da função open() é o file, o caminho relativo ou absoluto do arquivo em que você está tentando trabalhar.

Geralmente, utilizamos um caminho relativo. Ele indica onde o arquivo está localizado em relação à localização do script (arquivo Python) que está chamando a função open().

Por exemplo, o caminho nesta chamada de função:

open("names.txt") # O caminho relativo é "names.txt"

Ele contém apenas o nome do arquivo. Isso pode ser utilizado quando o arquivo que você deseja abrir está no mesmo diretório ou pasta em que o script em Python está localizado, desta forma:

image-7--1-

Se o arquivo estiver dentro de uma pasta, assim:

image-9
O arquivo names.txt está na pasta "data"

Então, devemos especificar o caminho para dizer à função que o arquivo se encontra dentro de outra pasta.

Neste exemplo, este seria o caminho:

open("data/names.txt")

Note que estamos escrevendo data/ primeiro (o nome da pasta seguido por /) e, então, names.txt (o nome do arquivo com a extensão).

💡 Dica: as três letras .txt que vêm depois do ponto, em names.txt, são a "extensão" do arquivo, ou seu tipo. Neste caso, .txt indica que ele é um arquivo de texto.

Segundo parâmetro: o modo

O segundo parâmetro da função open() é mode, uma string de apenas um caractere. Este único caractere diz ao Python o que você pretende fazer com o arquivo no seu programa.

Os modos disponíveis são:

  • Ler ("r").
  • Adicionar ("a")
  • Escrever ("w")
  • Criar ("x")

Você também pode escolher abrir o texto em:

  • Modo texto ("t")
  • Modo binário ("b")

Para utilizar o modo de texto ou binário, será necessário adicionar os caracteres no modo principal. Por exemplo: "wb" representa escrever em modo binário.

💡 Dica: os modos padrão são ler ("r") e texto ("t"), o que significa "abrir para a leitura de texto" ("rt"). Então, você não precisar declarar isso dentro da função open() se quiser utilizá-los, pois esses modos são declarados por padrão. Você pode simplesmente escrever open(<nome_do_arquivo>).

Por que modos?

Faz sentido para o Python garantir apenas certas permissões com base no que você planeja fazer com o arquivo. Por que ele deveria permitir que seu programa faça mais que o necessário? Por isso que existem os modos.

Pense — permitir que o programa faça mais do que o necessário pode ser problemático. Por exemplo, se você precisar apenas ler o conteúdo do arquivo, será perigoso permitir que o seu programa o modifique inesperadamente, o que pode, potencialmente, causar alguns bugs.

🔸 Como ler um arquivo

Agora que você sabe mais sobre os argumentos que a função open() utiliza, vamos ver como podemos abrir o arquivo e salvá-lo dentro de uma variável para a utilizarmos dentro do programa.

Esta é a sintaxe básica:

image-41--1-
Na caixa ciano: "Variável que armazenará o objeto de arquivo"

Estamos apenas atribuindo o valor retornado a uma variável. Por exemplo:

names_file = open("data/names.txt", "r")

Talvez você se pergunte: qual o tipo de valor retornado por open()?

Bem, um objeto de arquivo.

Vamos falar um pouco sobre eles.

Objetos de arquivo

De acordo com a documentação do Python, um objeto de arquivo é:

Um objeto expondo uma API orientada a arquivos (com métodos como read() ou write()) para um recurso subjacente.

Isto nos diz que um objeto de arquivo é um objeto que nos permite trabalhar e interagir com arquivos existentes no nosso programa em Python.

O objeto de arquivo possui atributos, como:

  • name: o nome do arquivo.
  • closed: True se o arquivo estiver fechado. Do contrário, False.
  • mode: o modo usado para abrir o arquivo.
image-57
Na caixa amarela: "Objeto de arquivo" | Na caixa verde: "Nome do atributo"

Por exemplo:

f = open("data/names.txt", "a")
print(f.mode) # Output: "a"

Agora vamos ver como acessar o conteúdo do arquivo através de objetos de arquivo.

Métodos para ler um arquivo

Para lermos um objeto de arquivo, precisamos ter uma forma de "interagir" com ele em nosso programa e é exatamente isso que métodos fazem. Vamos ver alguns desses métodos.

Read()

O primeiro método que precisamos aprender é read(), que retorna todo o conteúdo do arquivo como uma string.

image-11
Na caixa lilás: "O objeto de arquivo que você quer ler." | Na caixa verde: "(Opcional) Quantos bytes devem ser lidos"

Aqui temos um exemplo:

f = open("data/names.txt")
print(f.read())

O resultado é:

Nora
Gino
Timmy
William

Você pode usar a função type() para confirmar que o valor retornado por f.read() é uma string:

print(type(f.read()))

# Resultado
<class 'str'>

Sim, é uma string!

Neste caso, o arquivo inteiro foi o resultado, pois não definimos um número máximo de bytes, mas também podemos fazer isso.

Segue um exemplo:

f = open("data/names.txt")
print(f.read(3))

O valor retornado é limitado ao número de bytes:

Nor

❗️Importante: você precisar fechar o arquivo após a tarefa ter sido concluída para liberar os recursos associados a esse arquivo. Para fazer isso, chamamos o método close(), assim:

image-22
Na caixa laranja: "O objeto de arquivo que você quer fechar"

Readline() x Readlines()

Podemos ler o arquivo linha por linha através desses dois métodos. Eles têm uma pequena diferença. Vamos vê-los em detalhes.

readline()uma linha do arquivo até o fim dessa linha. Um caractere de nova linha (\n) à direita é mantido na string.

💡 Dica: como opção, podemos passar o tamanho, o número máximo de caracteres que desejamos incluir no resultado da string.

image-19
Na caixa laranja: "O objeto de arquivo que você quer ler" | Na caixa verde: "(Opcional) Quantos bytes devem ser lidos"

Por exemplo:

f = open("data/names.txt")
print(f.readline())
f.close()

O resultado é:

Nora

Essa é a primeira linha do arquivo.

Por outro lado, readlines() retorna uma lista com todas as linhas do arquivo como elementos individuais (strings). Esta é a sintaxe:

image-21--1-
Na caixa verde: "O objeto de arquivo que você quer ler" | Na caixa laranja: "(Opcional) Quantos bytes devem ser lidos"

Por exemplo:

f = open("data/names.txt")
print(f.readlines())
f.close()

O resultado é:

['Nora\n', 'Gino\n', 'Timmy\n', 'William']

Observe que há um \n (caractere de nova linha) ao final de cada string, excetuando a última.

💡 Dica: você pode obter a mesma lista com list(f).

Podemos trabalhar com esta lista no nosso programa designando-a a uma variável ou utilizando-a dentro de um laço:

f = open("data/names.txt")

for line in f.readlines():
    # Fazer algo com cada linha
    
f.close()

Também podemos iterar por f diretamente (o objeto de arquivo) em um laço:

f = open("data/names.txt", "r")

for line in f:
	# Do something with each line

f.close()

Esses são os principais métodos utilizados para se ler um objeto de arquivo. Vamos agora ver como criar arquivos.

🔹 Como criar um arquivo

Se você precisar criar um arquivo "dinamicamente" usando Python, podemos fazer isso com o modo "x".

Vamos ver como fazer isso. Esta é a sintaxe básica:

image-58
Na caixa laranja: "Criar o arquivo"

Aqui está um exemplo. Este é o meu diretório de trabalho atual:

image-29

Se eu executar esta linha de código:

f = open("new_file.txt", "x")

Um novo arquivo com aquele nome será criado:

image-30

Com este modo, você pode criar arquivos e escrevê-los dinamicamente usando os métodos que você aprenderá em instantes.

💡 Dica: o arquivo será inicializado vazio até que você o modifique.

Um fato curioso: se você tentar rodar esta linha novamente e um arquivo com o mesmo nome já existir, você verá este erro:

Traceback (most recent call last):
  File "<path>", line 8, in <module>
    f = open("new_file.txt", "x")
FileExistsError: [Errno 17] File exists: 'new_file.txt'

De acordo com a documentação do Python, essa exceção (erro em tempo de execução):

Aparece ao tentar criar um arquivo ou diretório que já existe.

Agora que você já sabe criar um arquivo, vamos ver como podemos modificá-lo.

🔸 Como modificar um arquivo

Para modificar (escrever em) um arquivo, precisamos utilizar o método write(). Há duas formas de se fazer isso (acrescentar ou escrever) baseado no modo em que você escolheu abrir o arquivo. Veremos isso em detalhes.

Acrescentar (append)

Acrescentar, aqui, significa acrescentar algo no final de outra coisa. O modo "a" permite que você abra um arquivo para acrescentar conteúdo a ele.

Por exemplo, se tivermos este arquivo:

image-43

e se quisermos adicionar uma nova linha a ele, podemos abrir o arquivo utilizando o modo "a" (append) e, em seguida, chamar o método write(), passando o conteúdo que queremos acrescentar como argumento.

Esta é a sintaxe básica para chamarmos o método write():

image-52
Na caixa azul: "Conteúdo que você deseja acrescentar"

Aqui vemos um exemplo:

f = open("data/names.txt", "a")
f.write("\nNew Line")
f.close()

💡 Dica: observe que estou adicionando um \n antes da linha para indicar que quero que apareça em uma nova linha, não em uma continuação da linha existente.

Este é o arquivo agora, após a execução do script:

image-45

💡 Dica: a nova linha pode não ser exibida no arquivo até que f.close() seja executado.

Escrever (write)

Às vezes, você pode querer excluir um conteúdo do arquivo e substituí-lo totalmente por um novo conteúdo. Podemos fazer isso utilizando o método write() se abrirmos o arquivo com o modo "w".

Aqui temos este arquivo de texto:

image-43--1-

Se executarmos este script:

f = open("data/names.txt", "w")
f.write("New Content")
f.close()

Este será o resultado:

image-46

Como pode ver, abrindo o arquivo no modo "w" e, depois, escrevendo, substituímos o conteúdo existente.

💡 Dica: o método write() retorna o número de caracteres escrito.

Se quisermos escrever várias linhas de uma vez, podemos usar o método writelines(), que leva uma lista de strings. Cada string representa uma linha a ser adicionada ao arquivo.

Aqui temos um exemplo. Este é o arquivo inicial:

image-43

Se executarmos este script:

f = open("data/names.txt", "a")
f.writelines(["\nline1", "\nline2", "\nline3"])
f.close()

As linhas serão adicionadas ao final do arquivo:

image-47

Abrir o arquivo para diversas operações

Agora que você sabe criar, ler e escrever em um arquivo, pode ser que você queira fazer mais que uma única ação no mesmo programa. Vamos ver o que acontece se tentarmos isso com os modos que aprendemos até agora:

Se você abrir um arquivo no modo "r" (read, ou ler) e, em seguida, tentar escrever nele:

f = open("data/names.txt")
f.write("New Content") # Tentativa de escrever
f.close()

Você receberá este erro:

Traceback (most recent call last):
  File "<path>", line 9, in <module>
    f.write("New Content")
io.UnsupportedOperation: not writable

Da mesma forma, se abrir um arquivo em modo "w" (write, ou escrever), e tentar ler o arquivo:

f = open("data/names.txt", "w")
print(f.readlines()) # Tentativa de ler
f.write("New Content")
f.close()

Receberá este erro:

Traceback (most recent call last):
  File "<path>", line 14, in <module>
    print(f.readlines())
io.UnsupportedOperation: not readable

O mesmo ocorrerá com o modo "a" (append, ou acrescentar).

Como podemos resolver isto? Para conseguirmos ler um arquivo e realizar outra operação dentro do mesmo programa, precisamos adicionar ao modo o símbolo  "+", desta forma:

f = open("data/names.txt", "w+") # Ler + Escrever
f = open("data/names.txt", "a+") # Ler + Acrescentar
f = open("data/names.txt", "r+") # Ler + Escrever

Útil, certo? Isso é o que você provavelmente utilizará nos seus programas, mas tenha certeza de incluir o modo para evitar possíveis bugs.

Às vezes, os arquivos são mais extensos do que o necessário. Vamos ver como excluir arquivos usando Python.

🔹 Como excluir arquivos

Para excluir arquivo utilizando Python, é preciso importar um módulo chamado os, que contém as funções para interagir com o seu sistema operacional.

💡 Dica: um dulo é um arquivo Python com variáveis, funções e classes relacionadas.

Em particular, você precisa da função remove(). Essa função recebe o caminho do arquivo como argumento e o exclui automaticamente.

image-56
Na caixa laranja: "Instrução de importação" | Na caixa lilás: "Chamada da função"

Vejamos um exemplo. Queremos remover o arquivo chamado sample_file.txt.

image-34--1--1

Para fazer isso, escrevemos este código:

import os
os.remove("sample_file.txt")
  • A primeira linha: import os é o "argumento de importação". Este argumento é escrito na parte superior do seu arquivo e dá acesso às funções definidas no módulo os.
  • A segunda linha: os.remove("sample_file.txt") remove o arquivo especificado.

💡 Dica: você pode usar um caminho absoluto ou um caminho relativo.

Agora que você sabe excluir arquivos, vamos ver uma ferramenta interessante... os gerenciadores de contexto!

🔸 Conheça os gerenciadores de contexto

Gerenciadores de contexto (context managers, em inglês) são construções do Python que tornam a sua vida mais fácil. Usando-os, você não precisa se lembrar de fechar um arquivo no final do seu programa e tem acesso ao arquivo em uma parte específica do programa que você escolher.

Sintaxe

Este é um exemplo de uso de um gerenciador de contexto para se trabalhar com arquivos:

image-33--1-
Nas caixas laranjas: "Palavras-chave" | Na caixa lilás: "Objeto de arquivo" | Na caixa verde: "Variável que será usada para se referir ao objeto de arquivo"

💡 Dica: o corpo do gerenciador de contexto deve ser indentado, assim como indentamos um laço, funções e classes. Se o código não for indentado, não será considerado parte do gerenciador de contexto.

Quando o corpo do gerenciador de contexto é finalizado, ele fecha o arquivo automaticamente.

with open("<path>", "<mode>") as <var>:
    # Trabalhando com o arquivo...

# O arquivo é fechado aqui!

Exemplo

Aqui temos um exemplo:

with open("data/names.txt", "r+") as f:
    print(f.readlines()) 

Este gerenciador de contexto abre o arquivo names.txt para a operação de leitura/escrita e designa o objeto de arquivo para uma variável f. Essa variável é usada no corpo do gerenciador de contexto para referenciar para o objeto de arquivo.

Tentando ler novamente

Depois do corpo ser feito, o arquivo é automaticamente fechado, então não pode ser lido sem abrir novamente. Mas espere! Nós temos uma linha que tenta ler novamente, como mostrado abaixo:

with open("data/names.txt", "r+") as f:
    print(f.readlines())

print(f.readlines()) # Tentando ler o arquivo novamente, fora do gerenciador de contexto

Vamos ver o que acontece:

Traceback (most recent call last):
  File "<path>", line 21, in <module>
    print(f.readlines())
ValueError: I/O operation on closed file.

Esse erro é lançado, pois estamos tentando ler um arquivo fechado. Incrível, certo? O gerenciador de contexto faz todo o trabalho pesado para nós, sendo legível e conciso.

🔹 Como lidar com exceções ao trabalharmos com arquivos

Quando você está trabalhando com arquivos, podem ocorrer erros. Às vezes, você não possui as permissões necessárias para modificar ou acessar um arquivo, ou o arquivo não existe.
Como programador, você precisa prever essas circunstâncias e lidar com elas no seu programa para evitar possíveis bugs e problemas que possam afetar a experiência do usuário.
Vamos ver as exceções mais comuns (erros de execução) que você pode encontrar enquanto trabalha com seus arquivos:

FileNotFoundError

De acordo com a documentação do Python, essa exceção:

Surge quando um arquivo ou diretório é solicitado, mas não existe.

Por exemplo, se o arquivo que você está tentando abrir não existir no seu diretório atual:

f = open("names.txt")

Você verá este erro:

Traceback (most recent call last):
  File "<path>", line 8, in <module>
    f = open("names.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'names.txt'

Vamos analisar esse erro, linha por linha:

  • File "<path>", line 8, in <module>. Essa linha informa a você que houve um erro quando o código no arquivo localizado em <path> estava em execução. Especificamente, quando a line 8 foi executada no <module>.
  • f = open("names.txt"). Essa é a linha que causou o erro.
  • FileNotFoundError: [Errno 2] No such file or directory: 'names.txt' . Essa linha diz que uma exceção FileNotFoundError aconteceu, pois o arquivo ou diretório names.txt não existe.

💡 Dica: o Python é muito descritivo com mensagens de erro, certo? Essa é uma grande vantagem durante o processo de depuração.

PermissionError

Essa é outra exceção comum ao se trabalhar com arquivos. De acordo com a documentação do Python, essa exceção:

Surge ao se tentar realizar uma operação sem os direitos de acesso adequados - por exemplo, permissões do sistema de arquivos.

Essa exceção ocorre quando tentamos ler ou modificar um arquivo que não possuímos permissão de acesso. Se você tentar, verá este erro:

Traceback (most recent call last):
  File "<path>", line 8, in <module>
    f = open("<file_path>")
PermissionError: [Errno 13] Permission denied: 'data'

IsADirectoryError

De acordo com a documentação do Python, essa exceção:

Surge quando uma operação de arquivo é solicitada em um diretório.

Essa exceção, em particular, ocorre quando você tenta abrir um arquivo ou trabalho em um diretório ao invés de um arquivo. Assim, tenha cuidado ao passar um caminho como um argumento.

Como lidar com exceções

Para lidar com exceções, você pode utilizar a declaração try/except. Com essas declarações, você pode "dizer" ao seu programa o que fazer caso aconteça algo inesperado.

Esta é a sintaxe básica:

try:
	# Tente executar esse código
except <type_of_exception>:
	# Se uma exceção desse tipo ocorrer, pare o processo e salte para este bloco
    

Aqui, você pode ver um exemplo de FileNotFoundError:

try:
    f = open("names.txt")
except FileNotFoundError:
    print("O arquivo não existe")

Basicamente, isso significa:

  • Tentar abrir o arquivo names.txt.
  • Se for lançado um erro do tipo FileNotFoundError, não parar o programa! Simplesmente imprimir uma declaração descritiva para o usuário.

💡 Dica: você pode escolher como lidar com a situação escrevendo um código apropriado no bloco except. Talvez você possa criar um arquivo, caso ele ainda não exista.

Para fechar o arquivo automaticamente após a tarefa (independentemente de uma exceção ter sido levantada ou não pelo bloco try), você pode adicionar o bloco finally.

try:
	# Tente executar esse código
except <exception>:
	# Se uma exceção desse tipo ocorrer, pare o processo imediatamente e salte para este bloco
finally: 
	# Faça isso após executar o código, mesmo que ocorra uma exceção

Este é um exemplo:

try:
    f = open("names.txt")
except FileNotFoundError:
    print("O arquivo não existe")
finally:
    f.close()

Existem várias maneiras de se customizar os argumentos try/except/finally. Você pode até adicionar um bloco else para rodar um bloco de código se nenhuma exceção tiver sido levantada no bloco try.

💡 Dica: para aprender mais sobre tratamento de exceções em Python, talvez você goste de ler meu artigo: "How to Handle Exceptions in Python: A Detailed Visual Introduction" (em inglês).

🔸 Em resumo

  • Você pode criar, ler, escrever em arquivos e excluí-los usando Python.
  • Objetos de arquivo têm seu próprio conjunto de métodos que você pode usar para trabalhar com eles em seu programa.
  • Os gerenciadores de contexto ajudam você a trabalhar com arquivos e gerenciá-los, fechando-os automaticamente quando uma tarefa é concluída.
  • O tratamento de exceções é fundamental em Python. Exceções comuns quando você está trabalhando com arquivos incluem FileNotFoundError, PermissionError e IsADirectoryError. Elas podem ser tratadas usando try/except/finally.

Espero que você tenha gostado do artigo e que ele tenha sido útil. Agora, você pode trabalhar com arquivos em seus projetos com Python.

Confira os cursos da autora. Siga a autora no Twitter. ⭐️