A resposta curta
Para verificar se um arquivo existe, use os.path.isfile() da biblioteca padrão. Ela retorna True quando o caminho aponta para um arquivo comum que existe e False caso contrário. Nunca lança erro para um caminho que não existe.
Os caminhos são relativos à pasta onde o programa roda (o diretório de trabalho atual), a menos que você passe um caminho absoluto como /home/ada/notes.txt ou C:\Users\Ada\notes.txt.
O resto desta página cobre as outras formas de fazer a pergunta, como elas diferem e o caso em que você não deveria fazê-la.
os.path.exists vs isfile vs isdir
O módulo os.path tem três verificações parecidas, e elas respondem perguntas um pouco diferentes:
| Função | Retorna True quando o caminho é |
|---|---|
os.path.exists(p) | qualquer coisa que exista: um arquivo, um diretório ou um link simbólico válido |
os.path.isfile(p) | um arquivo comum que existe |
os.path.isdir(p) | um diretório que existe |
A diferença aparece assim que um diretório entra na história:
Saída:
reports True False True
reports/summary.txt True True False
reports/old.txt False False False
os.path.exists("reports") é True mesmo sendo reports uma pasta. Se o seu código vai ler o caminho como arquivo, exists é a verificação errada: um diretório passaria nela, e open("reports") falharia depois (com IsADirectoryError no Linux e no macOS, PermissionError no Windows). Escolha isfile quando você quer um arquivo e isdir quando quer uma pasta.
Mais dois detalhes sobre essas três funções de os.path:
- Um link simbólico é seguido. Um link que aponta para um arquivo real conta como arquivo; um link quebrado (o alvo sumiu) retorna
Falsenas três. - Se o Python não tem permissão para olhar dentro de uma pasta, a verificação retorna
Falseem vez de lançarPermissionError.Falsequer dizer "não encontrado ou inacessível", não estritamente "não existe".
Verificando com pathlib
pathlib é a API de caminhos orientada a objetos da biblioteca padrão, e a maior parte do código novo usa ela. Um objeto Path tem as mesmas três verificações como métodos:
Path.exists(), Path.is_file() e Path.is_dir() se comportam como os.path.exists, isfile e isdir. O operador / junta partes do caminho com o separador certo para o sistema operacional, então folder / "summary.txt" funciona igual no Windows, no macOS e no Linux. Veja manipulação de arquivos para ler e escrever por meio de objetos Path.
Qual usar? Se o resto do seu código já passa objetos Path de um lado para outro, fique com o pathlib. Se você trabalha com strings simples e funções de os, os.path.isfile é igualmente correto. As respostas são as mesmas.
Por que verificar antes pode ser a escolha errada
O motivo mais comum para verificar se um arquivo existe é abri-lo logo depois:
import os
if os.path.isfile("config.txt"):
with open("config.txt") as f: # the file might be gone by now
settings = f.read()
else:
settings = ""
Isso tem uma brecha. Entre a chamada de isfile() e a chamada de open(), outro programa, outra thread ou o próprio usuário pode apagar ou renomear o arquivo. A verificação disse True, a abertura falha mesmo assim, e o programa quebra com FileNotFoundError de qualquer jeito. Essa brecha se chama condição de corrida, ou "time of check to time of use" (momento da verificação contra momento do uso). É rara no seu notebook e bem menos rara num servidor movimentado onde vários processos dividem uma pasta.
A solução é pular a verificação separada e deixar o próprio open() ser a verificação. O Python lança FileNotFoundError quando o arquivo não existe, e você trata isso no except:
Saída:
theme=dark
(no settings file, using defaults)
Agora há uma operação em vez de duas, então não há corrida possível. Esse estilo tem nome na comunidade Python: EAFP, "easier to ask forgiveness than permission" (é mais fácil pedir perdão do que permissão). O estilo oposto, verificar antes, é LBYL, "look before you leap" (olhe antes de pular). O Python prefere EAFP para trabalhar com arquivos porque o sistema operacional é o único que sabe a resposta no momento em que você abre o arquivo.
FileNotFoundError não é a única coisa que pode dar errado. Um caminho que é um diretório lança IsADirectoryError (PermissionError no Windows), e um arquivo que você não pode ler lança PermissionError. As três são subclasses de OSError, então except OSError: pega de uma vez todos os casos de "não consegui abrir". A página de exceções explica como escolher entre capturar um erro específico e capturar uma família inteira.
Quando uma verificação simples basta
Verificar antes não é errado em todos os casos. É a ferramenta certa quando você só precisa da resposta e não vai mexer no arquivo na linha seguinte:
- escolher qual mensagem mostrar ("3 jogos salvos encontrados")
- validar um caminho que o usuário digitou antes de começar um trabalho longo
- pular um trabalho que já foi feito, quando uma resposta desatualizada só custa uma repetição
A regra prática: se você vai abrir, ler, escrever ou apagar o arquivo, faça isso dentro de try. Se só quer saber, isfile() ou Path.is_file() servem.
Criar um arquivo só se ele não existir
A pergunta inversa também aparece: "escreva este arquivo, mas nunca sobrescreva um que já existe". A versão óbvia tem a mesma corrida de antes:
if not os.path.exists("report.txt"):
with open("report.txt", "w") as f: # another process may create it first
f.write("new report\n")
O modo "x" (criação exclusiva) faz os dois passos em um. Ele cria o arquivo, ou lança FileExistsError se o nome já estiver ocupado:
Saída:
attempt 1: created report.txt
attempt 2: report.txt already exists, left it alone
Para pastas, os.makedirs(path, exist_ok=True) e Path(path).mkdir(parents=True, exist_ok=True) criam o diretório e qualquer pasta pai que falte, e não fazem nada se ele já existir. Não precisa chamar isdir() antes.
Erros comuns
- Usar
exists()quando você quer um arquivo. Um diretório com o mesmo nome passa na verificação. Useisfile()ouPath.is_file(). - Esquecer de onde partem os caminhos relativos.
"data.txt"é procurado no diretório de trabalho atual, que é de onde você iniciou o programa, não necessariamente a pasta onde está o script. Para achar um arquivo ao lado do script, monte o caminho a partir dePath(__file__).parent. - Verificar e depois abrir. O arquivo pode mudar nesse meio tempo. Abra dentro de
trye trateFileNotFoundError. - Capturar qualquer exceção.
except Exception:em volta deopen()também esconde erros de digitação e bugs no código que lê o arquivo. CaptureFileNotFoundErrorouOSError.
Perguntas frequentes
Como verifico se um arquivo existe em Python?
Importe os e chame os.path.isfile("data.txt"), que retorna True apenas para um arquivo comum que existe. Com pathlib é Path("data.txt").is_file(). Use os.path.exists() ou Path.exists() quando um diretório com esse nome também deve contar.
Qual a diferença entre os.path.exists e os.path.isfile?
os.path.exists(p) é True para qualquer coisa naquele caminho: um arquivo, um diretório ou um link simbólico que aponta para algo real. os.path.isfile(p) é True apenas para um arquivo comum, então retorna False para um diretório. os.path.isdir(p) é o equivalente para diretórios.
Devo verificar se um arquivo existe antes de abri-lo?
Normalmente não. O arquivo pode ser apagado ou criado entre a verificação e a chamada de open(), então a verificação não garante nada. Abra o arquivo direto dentro de try e trate FileNotFoundError no except. Uma verificação separada é o certo quando você só precisa da resposta, por exemplo para decidir qual mensagem mostrar.
Como crio um arquivo só se ele não existir?
Abra com o modo "x": open("report.txt", "x"). O Python cria o arquivo, ou lança FileExistsError se já houver algo com esse nome. A verificação e a criação acontecem em um passo só, então nenhum outro programa consegue se meter entre as duas.