Como verifico se um arquivo existe ou não, sem usar a try
instrução?
fonte
Como verifico se um arquivo existe ou não, sem usar a try
instrução?
Se o motivo que você está verificando é para que você possa fazer algo assim if file_exists: open_it()
, é mais seguro usar uma try
tentativa de abri-lo. Verificar e abrir o risco de o arquivo ser excluído ou movido ou algo entre quando você verifica e quando tenta abri-lo.
Se você não planeja abrir o arquivo imediatamente, pode usar os.path.isfile
Retorne
True
se path for um arquivo regular existente. Isso segue links simbólicos, portanto, islink () e isfile () podem ser verdadeiros para o mesmo caminho.
import os.path
os.path.isfile(fname)
se você precisa ter certeza de que é um arquivo.
A partir do Python 3.4, o pathlib
módulo oferece uma abordagem orientada a objetos (suportada pathlib2
no Python 2.7):
from pathlib import Path
my_file = Path("/path/to/file")
if my_file.is_file():
# file exists
Para verificar um diretório, faça:
if my_file.is_dir():
# directory exists
Para verificar se um Path
objeto existe independentemente de ser um arquivo ou diretório, use exists()
:
if my_file.exists():
# path exists
Você também pode usar resolve(strict=True)
em um try
bloco:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
FileNotFoundError
foi introduzido no Python 3. Se você também precisa apoiar Python 2.7, bem como Python 3, você pode usarIOError
em vez (queFileNotFoundError
subclasses) stackoverflow.com/a/21368457/1960959open('file', 'r+')
) e depois procurar o final.Você tem a
os.path.exists
função:Isso retorna
True
para arquivos e diretórios, mas você pode usarpara testar se é um arquivo especificamente. Segue links simbólicos.
fonte
Ao contrário
isfile()
,exists()
retornaráTrue
para diretórios. Portanto, dependendo se você deseja apenas arquivos simples ou também diretórios, você usaráisfile()
ouexists()
. Aqui está uma saída REPL simples:fonte
fonte
Use
os.path.isfile()
comos.access()
:fonte
os.access()
retornará false.import os
você não precisaimport os.path
novamente, pois já faz parteos
. Você só precisa importaros.path
se deseja usar funções deos.path
e não deos
si mesmo, para importar algo menor, mas à medida que você usaos.access
eos.R_OK
, a segunda importação não é necessária.fonte
Embora quase todas as formas possíveis tenham sido listadas em (pelo menos uma das) respostas existentes (por exemplo, coisas específicas do Python 3.4 foram adicionadas), tentarei agrupar tudo.
Nota : cada parte do código da biblioteca padrão do Python que vou postar pertence à versão 3.5.3 .
Declaração do problema :
Possíveis soluções :
[Python 3]: os.path. existe ( caminho ) (verifique também outros membros da família como função
os.path.isfile
,os.path.isdir
,os.path.lexists
para comportamentos ligeiramente diferentes)Tudo bem, mas se seguir a árvore de importação:
os.path
- posixpath.py ( ntpath.py )genericpath.py , linha ~ # 20 +
é apenas um bloco try / except em torno de [Python 3]: os. stat ( caminho, *, dir_fd = Nenhum, follow_symlinks = True ) . Portanto, seu código é try / except free, mas mais baixo no framestack existe (pelo menos) um desses blocos. Isso também se aplica a outras funções ( inclusive
os.path.isfile
).1.1 [Python 3]: caminho. is_file ()
Sob o capô, ele faz exatamente a mesma coisa ( pathlib.py , linha ~ # 1330 ):
[Python 3]: com gerenciadores de contexto de instrução . Ou:
Crie um:
E seu uso - replicarei o
os.path.isfile
comportamento (observe que isso é apenas para fins de demonstração, não tente escrever esse código para produção ):Use [Python 3]: contextlib. suprimir ( * exceções ) - que foi projetado especificamente para suprimir seletivamente exceções
Mas, eles parecem ser wrappers sobre blocos try / except / else / finalmente , como [Python 3]: A declaração with afirma:
Funções transversais do sistema de arquivos (e pesquise os resultados pelos itens correspondentes)
[Python 3]: os. listdir ( caminho = '.' ) (ou [Python 3]: os. scandir ( caminho = '.' ) no Python v 3.5 +, backport: [PyPI]: scandir )
Sob o capô, ambos usam:
via [GitHub]: python / cpython - (mestre) cpython / Módulos / posixmodule.c
os.listdir
(os.scandir
quando disponível)glob.glob
)os.listdir
Como essas iterações nas pastas (na maioria dos casos) são ineficientes para o nosso problema (há exceções, como glob bing sem caracteres curinga - como o @ShadowRanger apontou), então não vou insistir nelas. Sem mencionar que, em alguns casos, o processamento do nome do arquivo pode ser necessário.
[Python 3]: os. de acesso ( de caminho, modo, *, dir_fd = None, effective_ids = false, follow_symlinks = true ) cujo comportamento está perto
os.path.exists
(na verdade, é mais amplo, principalmente por causa da 2 nd argumento)os.access("/tmp", os.F_OK)
Desde que eu também trabalho em C , eu uso este método, mas também porque sob o capô, ele chama nativa API s (mais uma vez, através de "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c" ), mas também abre uma porta para um possível usuário erros e não é tão Python ic quanto outras variantes. Portanto, como o @AaronHall apontou corretamente, não o use, a menos que você saiba o que está fazendo:
Nota : chamar APIs nativas também é possível via [Python 3]: ctypes - Uma biblioteca de funções estrangeira para Python , mas na maioria dos casos é mais complicado.
( Específico para Windows ): Como o vcruntime * ( msvcr * ) .dll exporta uma família de funções [MS.Docs]: _access, _waccess , aqui está um exemplo:
Notas :
os.F_OK
a chamada, mas isso é apenas para esclarecer (seu valor é 0 )A contraparte do Lnx ( Ubtu (16 x64) ) também:
Notas :
Em vez disso, codifique o caminho da libc ( "/lib/x86_64-linux-gnu/libc.so.6" ) que pode (e provavelmente irá) variar entre os sistemas. Nenhum (ou a string vazia) pode ser passado ao construtor CDLL (
ctypes.CDLL(None).access(b"/tmp", os.F_OK)
) De acordo com [man7]: DLOPEN (3) :__declspec(dllexport)
(por que diabos a pessoa comum faria isso?), o programa principal é carregável, mas praticamente inutilizávelInstale algum módulo de terceiros com recursos do sistema de arquivos
Provavelmente, contará com uma das maneiras acima (talvez com pequenas personalizações).
Um exemplo seria (novamente, específico para Win ) [GitHub]: mhammond / pywin32 - Extensões do Python para Windows (pywin32) , que é um wrapper do Python sobre o WINAPI s.
Mas, como isso é mais uma solução alternativa, estou parando aqui.
Outra solução alternativa (lame) ( gainarie ) é (como eu gosto de chamar), a abordagem sysadmin : use Python como um wrapper para executar comandos de shell
Vitória :
Nix ( Lnx ( Ubtu )):
Bottom line :
Nota (s) final (is) :
fonte
glob.iglob
(eglob.glob
também) são baseadosos.scandir
, por isso é preguiçoso agora; para obter o primeiro hit em um diretório com 10 milhões de arquivos, você só escaneia até chegar ao primeiro hit. E mesmo antes da 3.6, se você usarglob
métodos sem curingas, a função é inteligente: ela sabe que você pode ter apenas um hit, simplificando o globbing para apenasos.path.isdir
ouos.path.lexists
(dependendo se o caminho termina/
).os.path.isdir
ouos.path.lexist
uma vez que é um monte de chamadas e seqüências de funções no nível Python operações antes de decidir que o caminho eficiente é viável, mas nenhuma chamada adicional do sistema ou trabalho de E / S, que é de magnitude mais lenta).Essa é a maneira mais simples de verificar se existe um arquivo. Só porque o arquivo existia quando você verificou não garante que ele estará lá quando você precisar abri-lo.
fonte
O Python 3.4+ possui um módulo de caminho orientado a objetos: pathlib . Usando este novo módulo, você pode verificar se existe um arquivo como este:
Você pode (e geralmente deve) ainda usar um
try/except
bloco ao abrir arquivos:O módulo pathlib possui muitas coisas interessantes: globbing conveniente, verificação do proprietário do arquivo, junção de caminho mais fácil etc. Vale a pena conferir. Se você estiver em um Python mais antigo (versão 2.6 ou posterior), ainda poderá instalar o pathlib com o pip:
Importe-o da seguinte maneira:
fonte
Prefira a instrução try. É considerado um estilo melhor e evita condições de corrida.
Não aceite minha palavra. Há bastante apoio para essa teoria. Aqui estão alguns:
fonte
try...except
não ajuda a resolver esse problema de qualquer maneira.except:
cláusula fará com que uma exceção resultante dessa parte do código gere uma mensagem confusa (segundo erro gerado durante o processamento do primeiro.)Agora disponível desde o Python 3.4, importe e instancie um
Path
objeto com o nome do arquivo e verifique ois_file
método (observe que isso retorna True para links simbólicos que também apontam para arquivos regulares):Se você estiver no Python 2, poderá fazer o backport do módulo pathlib a partir do pypi
pathlib2
, ou verificarisfile
noos.path
módulo:Agora, a descrição acima é provavelmente a melhor resposta direta pragmática aqui, mas há a possibilidade de uma condição de corrida (dependendo do que você está tentando realizar) e o fato de a implementação subjacente usar a
try
, mas o Python usatry
em toda parte em sua implementação.Como o Python usa em
try
qualquer lugar, não há realmente nenhuma razão para evitar uma implementação que o utilize.Mas o restante desta resposta tenta considerar essas advertências.
Resposta mais longa e pedante
Disponível desde o Python 3.4, use o novo
Path
objeto empathlib
. Note que isso.exists
não está certo, porque diretórios não são arquivos (exceto no sentido unix de que tudo é um arquivo).Então, precisamos usar
is_file
:Aqui está a ajuda sobre
is_file
:Então, vamos pegar um arquivo que sabemos que é um arquivo:
Por padrão,
NamedTemporaryFile
exclui o arquivo quando fechado (e será fechado automaticamente quando não houver mais referências a ele).Se você se aprofundar na implementação , verá que
is_file
usatry
:Condições da corrida: Por que gostamos de tentar
Gostamos
try
porque evita as condições da corrida. Comtry
, você simplesmente tenta ler seu arquivo, esperando que ele esteja lá; caso contrário, captura a exceção e executa qualquer comportamento de fallback que faça sentido.Se você deseja verificar a existência de um arquivo antes de tentar lê-lo e pode estar excluindo-o e estar usando vários threads ou processos, ou outro programa conhece esse arquivo e pode excluí-lo - você corre o risco de uma condição de corrida, se você verificar que ela existe, porque você está correndo para abri-la antes que sua condição (sua existência) mude.
As condições de corrida são muito difíceis de depurar porque há uma janela muito pequena na qual elas podem causar falha no seu programa.
Mas se essa é sua motivação, você pode obter o valor de uma
try
declaração usando osuppress
gerenciador de contexto.Evitando condições de corrida sem uma declaração de tentativa:
suppress
O Python 3.4 nos fornece o
suppress
gerenciador de contexto (anteriormente oignore
gerenciador de contexto), que semanticamente faz exatamente a mesma coisa em menos linhas, enquanto também (pelo menos superficialmente) atende à solicitação original para evitar umatry
declaração:Uso:
Para Pythons anteriores, você poderia fazer o seu próprio
suppress
, mas sem umtry
será mais detalhado do que com. Eu acredito que essa é realmente a única resposta que não usatry
em nenhum nível no Python que possa ser aplicada antes do Python 3.4, porque ele usa um gerenciador de contexto:Talvez mais fácil com uma tentativa:
Outras opções que não atendem à solicitação "sem tentativa":
isfile
dos documentos :
Mas se você examinar a fonte dessa função, verá que ela realmente usa uma instrução try:
Tudo o que está fazendo é usar o caminho fornecido para ver se ele pode obter estatísticas, capturar
OSError
e verificar se é um arquivo, se não gerou a exceção.Se você pretende fazer algo com o arquivo, sugiro que tente diretamente com uma tentativa, exceto para evitar uma condição de corrida:
os.access
Disponível para Unix e Windows
os.access
, é necessário , mas para usá-lo, você deve passar sinalizadores, e não diferencia entre arquivos e diretórios. Isso é mais usado para testar se o usuário que está chamando real tem acesso em um ambiente de privilégios elevados:Também sofre dos mesmos problemas de condição de corrida que
isfile
. Dos documentos :Evite usar
os.access
. É uma função de baixo nível que tem mais oportunidades de erro do usuário do que os objetos e funções de nível superior discutidos acima.Crítica de outra resposta:
Outra resposta diz o seguinte
os.access
:Esta resposta diz que prefere um método não pitonico e propenso a erros, sem justificativa. Parece incentivar os usuários a usar APIs de baixo nível sem entendê-las.
Ele também cria um gerenciador de contexto que, ao retornar incondicionalmente
True
, permite todas as exceções (incluindoKeyboardInterrupt
eSystemExit
!) Passem silenciosamente, o que é uma boa maneira de ocultar bugs.Isso parece incentivar os usuários a adotar práticas inadequadas.
fonte
A importação
os
facilita a navegação e a execução de ações padrão com o sistema operacional.Para referência, consulte Como verificar se existe um arquivo usando Python?
Se você precisar de operações de alto nível, use
shutil
.fonte
os.path.exists
retorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadasos.path.isfile
.Teste para arquivos e pastas com
os.path.isfile()
,os.path.isdir()
eos.path.exists()
Supondo que o "caminho" seja um caminho válido, esta tabela mostra o que é retornado por cada função para arquivos e pastas:
Você também pode testar se um arquivo é um determinado tipo de arquivo usado
os.path.splitext()
para obter a extensão (se você ainda não o conhece)fonte
Em 2016, a melhor maneira ainda está usando
os.path.isfile
:Ou no Python 3 você pode usar
pathlib
:fonte
pathlib
é a solução OOP do python para caminhos. Você pode fazer muito mais com isso. Se você só precisa verificar a existência, a vantagem não é tão grande.Não parece haver uma diferença funcional significativa entre try / except e
isfile()
, portanto, você deve usar qual deles faz sentido.Se você quiser ler um arquivo, se existir, faça
Mas se você quiser renomear um arquivo, se ele existir, e, portanto, não precisar abri-lo, faça
Se você deseja gravar em um arquivo, se ele não existir, faça
Se você precisar de bloqueio de arquivos, isso será diferente.
fonte
os.path.exists
retorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadasos.path.isfile
.filepath
com o tempo certo, e BAM , você substitui o arquivo de destino. Você deve fazeropen(filepath, 'wx')
em umtry...except
bloco para evitar o problema.OSError
sefilepath + '.old'
já existir: "No Windows, se o dst já existir, o OSError será gerado mesmo que seja um arquivo; pode não haver maneira de implementar uma renomeação atômica quando o dst nomeia um arquivo existente ".os.replace
realiza uma substituição silenciosa do arquivo de destino (é idêntico aoos.rename
comportamento do Linux) (apenas erros se o nome do destino existir e for um diretório). Portanto, você está preso no 2.x, mas os usuários do Py3 têm uma boa opção há vários anos.rename
exemplo: ainda deve ser feito comtry
/except
.os.rename
(ouos.replace
no Python moderno) é atômico; fazê-lo verificar e renomear introduz uma corrida desnecessária e chamadas de sistema adicionais. Apenas façatry: os.replace(filepath, filepath + '.old') except OSError: pass
Você pode tentar isso (mais seguro):
A saída seria:
Então, dependendo do resultado, seu programa pode continuar em execução a partir daí ou você pode codificar para pará-lo, se desejar.
fonte
try
Embora eu sempre recomende usar
try
eexcept
instruções, aqui estão algumas possibilidades para você (meu favorito pessoal é usaros.access
):Tente abrir o arquivo:
A abertura do arquivo sempre verificará a existência do arquivo. Você pode criar uma função da seguinte maneira:
Se for False, interromperá a execução com um IOError ou OSError sem tratamento nas versões posteriores do Python. Para capturar a exceção, você deve usar uma tentativa, exceto a cláusula. Obviamente, você sempre pode usar uma
try
declaração exceto `assim (obrigado a hsandt por me fazer pensar):Use
os.path.exists(path)
:Isso verificará a existência do que você especificar. No entanto, ele verifica se há arquivos e diretórios, portanto, tenha cuidado com o uso.
Use
os.access(path, mode)
:Isso verificará se você tem acesso ao arquivo. Ele irá verificar as permissões. Com base na documentação do os.py, ao digitar
os.F_OK
, ele verificará a existência do caminho. No entanto, usar isso criará uma brecha na segurança, pois alguém pode atacar seu arquivo usando o tempo entre verificar as permissões e abrir o arquivo. Você deve ir diretamente para abrir o arquivo em vez de verificar suas permissões. ( EAFP vs LBYP ). Se você não abrir o arquivo posteriormente e apenas verificar sua existência, poderá usá-lo.Enfim, aqui:
Também devo mencionar que existem duas maneiras pelas quais você não poderá verificar a existência de um arquivo. A questão será
permission denied
ouno such file or directory
. Se você pegar umIOError
, defina oIOError as e
(como minha primeira opção) e digiteprint(e.args)
para que você possa determinar o problema. Espero que ajude! :)fonte
Data: 2017-12-04
Todas as soluções possíveis foram listadas em outras respostas.
Uma maneira intuitiva e discutível de verificar se existe um arquivo é o seguinte:
Fiz uma folha de dicas exaustiva para sua referência:
fonte
Se o arquivo for para abrir, você poderá usar uma das seguintes técnicas:
ATUALIZAR
Apenas para evitar confusão e com base nas respostas que recebi, a resposta atual localiza um arquivo ou um diretório com o nome fornecido.
fonte
os.path.exists
retorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadasos.path.isfile
.Além disso,
os.access()
:Sendo
R_OK
,W_OK
eX_OK
as bandeiras para testar permissões ( doc ).fonte
SRC: http://www.pfinn.net/python-check-if-file-exists.html
fonte
Se você importou NumPy já para outros fins, então não há necessidade de importar outras bibliotecas, como
pathlib
,os
,paths
, etc.Isso retornará verdadeiro ou falso com base em sua existência.
fonte
Você pode escrever a sugestão de Brian sem o
try:
.suppress
faz parte do Python 3.4. Em versões mais antigas, você pode escrever rapidamente sua própria supressão:fonte
Sou o autor de um pacote que existe há cerca de 10 anos e tem uma função que aborda essa questão diretamente. Basicamente, se você estiver em um sistema não Windows, ele será usado
Popen
para acessarfind
. No entanto, se você estiver no Windows, ele se replicafind
com um andador eficiente do sistema de arquivos.O código em si não usa um
try
bloco ... exceto para determinar o sistema operacional e, assim, direcioná-lo para o estilo "Unix"find
ou para o manualfind
. Os testes de tempo mostraram que o processo detry
determinação do sistema operacional foi mais rápido, então eu usei um lá (mas em nenhum outro lugar).E o doc…
A implementação, se você preferir, está aqui: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190
fonte
Verifique se existe arquivo ou diretório
Você pode seguir estas três maneiras:
fonte
Adicionando mais uma ligeira variação que não é exatamente refletida nas outras respostas.
Isso manipulará o caso do
file_path
serNone
ou da sequência vazia.Adicionando uma variante com base na sugestão do Shahbaz
Adicionando uma variante com base na sugestão de Peter Wood
fonte
if (x) return true; else return false;
é realmente justoreturn x
. Suas últimas quatro linhas podem se tornarreturn os.path.isfile(file_path)
. Enquanto estamos nisso, toda a função pode ser simplificada comoreturn file_path and os.path.isfile(file_path)
.return x
no caso deif (x)
. O Python considerará uma string vazia False; nesse caso, retornaríamos uma string vazia em vez de um bool. O objetivo desta função é sempre retornar bool.x
éos.path.isfile(..)
assim que já é booleano.os.path.isfile(None)
gera uma exceção e foi por isso que adicionei o if check. Eu provavelmente poderia envolvê-lo em uma tentativa / exceto em vez disso, mas achei que era mais explícito dessa maneira.return file_path and os.path.isfile(file_path)
Aqui está um comando Python de 1 linha para o ambiente de linha de comando do Linux. Acho isso MUITO HANDY, já que não sou um cara gostoso do Bash.
Espero que isto seja útil.
fonte
[ -f "${file}" ] && echo "file found" || echo "file not found"
(que é igual aif [ ... ]; then ...; else ...; fi
).Você pode usar a biblioteca "OS" do Python:
fonte
os.path.exists
retorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadasos.path.isfile
.exists
bem. Se o objetivo é determinar se é seguro abrir um arquivo presumivelmente existente, as críticas são justificadas e existem não são suficientemente precisas. Infelizmente, o OP não especifica qual é o objetivo desejado (e provavelmente não o fará mais).Em 2016, essa ainda é a maneira mais fácil de verificar se existe um arquivo e se é um arquivo:
isfile
é realmente apenas um método auxiliar que usa internamenteos.stat
estat.S_ISREG(mode)
por baixo. Esteos.stat
é um método de nível inferior que fornecerá informações detalhadas sobre arquivos, diretórios, soquetes, buffers e muito mais. Mais sobre o os.stat aquiNota: No entanto, essa abordagem não bloqueia o arquivo de maneira alguma e, portanto, seu código pode ficar vulnerável a erros de " verificação do tempo de uso " ( TOCTTOU ).
Portanto, criar exceções é considerado uma abordagem aceitável e pitônica para controle de fluxo em seu programa. E deve-se considerar manipular arquivos ausentes com IOErrors, em vez de
if
instruções ( apenas um conselho ).fonte
fonte
isReadableFile(path,fileName)
vai voltarTrue
se o arquivo está acessível e legível pelo processo \ Programas \ fio