Como verifico se existe um arquivo sem exceções?

5607

Como verifico se um arquivo existe ou não, sem usar a tryinstrução?

spence91
fonte

Respostas:

5153

Se o motivo que você está verificando é para que você possa fazer algo assim if file_exists: open_it(), é mais seguro usar uma trytentativa 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 Truese 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 pathlibmódulo oferece uma abordagem orientada a objetos (suportada pathlib2no 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 Pathobjeto 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 trybloco:

try:
    my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
    # doesn't exist
else:
    # exists
rslite
fonte
40
no que diz respeito à primeira observação (use "try" se verificar antes de abrir), infelizmente isso não funcionará se você deseja abrir para anexar, garantindo que ela exista antes, pois o modo 'a' será criado se não existir.
makapuf
6
Note-se que FileNotFoundErrorfoi introduzido no Python 3. Se você também precisa apoiar Python 2.7, bem como Python 3, você pode usar IOErrorem vez (que FileNotFoundErrorsubclasses) stackoverflow.com/a/21368457/1960959
scottclowe
7
@makapuf Você pode abri-lo para "atualizar" ( open('file', 'r+')) e depois procurar o final.
Kyrill
2111

Você tem a os.path.existsfunção:

import os.path
os.path.exists(file_path)

Isso retorna Truepara arquivos e diretórios, mas você pode usar

os.path.isfile(file_path)

para testar se é um arquivo especificamente. Segue links simbólicos.

PierreBdR
fonte
966

Ao contrário isfile(), exists()retornará Truepara diretórios. Portanto, dependendo se você deseja apenas arquivos simples ou também diretórios, você usará isfile()ou exists(). Aqui está uma saída REPL simples:

>>> os.path.isfile("/etc/password.txt")
True
>>> os.path.isfile("/etc")
False
>>> os.path.isfile("/does/not/exist")
False
>>> os.path.exists("/etc/password.txt")
True
>>> os.path.exists("/etc")
True
>>> os.path.exists("/does/not/exist")
False
bortzmeyer
fonte
623
import os.path

if os.path.isfile(filepath):
Paulo
fonte
320

Use os.path.isfile()com os.access():

import os

PATH = './file.txt'
if os.path.isfile(PATH) and os.access(PATH, os.R_OK):
    print("File exists and is readable")
else:
    print("Either the file is missing or not readable")
Yugal Jindle
fonte
60
ter várias condições, algumas das quais supérfluas, é menos clara e explícita.
Wim
10
Também é redundante. Se o arquivo não existir, os.access()retornará false.
Marquês de Lorne
9
@EJP No Linux, os arquivos podem existir, mas não são acessíveis.
e-info128
8
desde que import osvocê não precisa import os.pathnovamente, pois já faz parte os. Você só precisa importar os.pathse deseja usar funções de os.pathe não de ossi mesmo, para importar algo menor, mas à medida que você usa os.accesse os.R_OK, a segunda importação não é necessária.
Jester
287
import os
os.path.exists(path) # Returns whether the path (directory or file) exists or not
os.path.isfile(path) # Returns whether the file exists or not
benéfico
fonte
2
Geralmente, não é uma boa prática nomear variáveis ​​da mesma forma que nomes de métodos.
Homunculus Reticulli 03/04
245

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 :

  1. Verificar a existência de arquivo ( discutível : também pasta (arquivo "especial"))?)
  2. Não use os blocos try / except / else / finalmente

Possíveis soluções :

  1. [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.lexistspara comportamentos ligeiramente diferentes)

    os.path.exists(path)

    Retorne Truese path se referir a um caminho existente ou a um descritor de arquivo aberto. Retorna Falsepara links simbólicos quebrados. Em algumas plataformas, essa função pode retornar Falsese a permissão não for concedida para executar os.stat () no arquivo solicitado, mesmo que o caminho exista fisicamente.

    Tudo bem, mas se seguir a árvore de importação:

    • os.path- posixpath.py ( ntpath.py )

      • genericpath.py , linha ~ # 20 +

        def exists(path):
            """Test whether a path exists.  Returns False for broken symbolic links"""
            try:
                st = os.stat(path)
            except os.error:
                return False
            return True

    é 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 ()

    • É uma maneira mais sofisticada (e mais python ic) de lidar com caminhos, mas
    • Sob o capô, ele faz exatamente a mesma coisa ( pathlib.py , linha ~ # 1330 ):

      def is_file(self):
          """
          Whether this path is a regular file (also True for symlinks pointing
          to regular files).
          """
          try:
              return S_ISREG(self.stat().st_mode)
          except OSError as e:
              if e.errno not in (ENOENT, ENOTDIR):
                  raise
              # Path doesn't exist or is a broken symlink
              # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
              return False
  2. [Python 3]: com gerenciadores de contexto de instrução . Ou:

    • Crie um:

      class Swallow:  # Dummy example
          swallowed_exceptions = (FileNotFoundError,)
      
          def __enter__(self):
              print("Entering...")
      
          def __exit__(self, exc_type, exc_value, exc_traceback):
              print("Exiting:", exc_type, exc_value, exc_traceback)
              return exc_type in Swallow.swallowed_exceptions  # only swallow FileNotFoundError (not e.g. TypeError - if the user passes a wrong argument like None or float or ...)
      • E seu uso - replicarei o os.path.isfilecomportamento (observe que isso é apenas para fins de demonstração, não tente escrever esse código para produção ):

        import os
        import stat
        
        
        def isfile_seaman(path):  # Dummy func
            result = False
            with Swallow():
                result = stat.S_ISREG(os.stat(path).st_mode)
            return result
    • 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:

    Isso permite que tentativas comuns ... exceto ... finalmente , padrões de uso sejam encapsulados para reutilização conveniente.

  3. Funções transversais do sistema de arquivos (e pesquise os resultados pelos itens correspondentes)


    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.

  4. [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)

    • as permissões de usuário podem restringir a "visibilidade" do arquivo, conforme o documento afirma:

      ... teste se o usuário que está chamando tem o acesso especificado ao caminho . O modo deve ser F_OK para testar a existência do caminho ...

    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:

    Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os, ctypes
    >>> ctypes.CDLL("msvcrt")._waccess(u"C:\\Windows\\System32\\cmd.exe", os.F_OK)
    0
    >>> ctypes.CDLL("msvcrt")._waccess(u"C:\\Windows\\System32\\cmd.exe.notexist", os.F_OK)
    -1

    Notas :

    • Embora não seja uma boa prática, estou usando os.F_OKa chamada, mas isso é apenas para esclarecer (seu valor é 0 )
    • Estou usando _waccess para que o mesmo código funcione em Python3 e Python2 (apesar das diferenças relacionadas a unicode entre eles)
    • Embora isso atinja uma área muito específica, não foi mencionado em nenhuma das respostas anteriores


    A contraparte do Lnx ( Ubtu (16 x64) ) também:

    Python 3.5.2 (default, Nov 17 2016, 17:05:23)
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os, ctypes
    >>> ctypes.CDLL("/lib/x86_64-linux-gnu/libc.so.6").access(b"/tmp", os.F_OK)
    0
    >>> ctypes.CDLL("/lib/x86_64-linux-gnu/libc.so.6").access(b"/tmp.notexist", os.F_OK)
    -1

    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) :

      Se o nome do arquivo for NULL, o identificador retornado será para o programa principal. Quando atribuído a dlsym (), esse identificador causa uma pesquisa por um símbolo no programa principal, seguido por todos os objetos compartilhados carregados na inicialização do programa e, em seguida, todos os objetos compartilhados carregados por dlopen () com o sinalizador RTLD_GLOBAL .

      • O programa principal (atual) ( python ) está vinculado à libc , portanto seus símbolos (incluindo acesso ) serão carregados
      • Isso deve ser tratado com cuidado, pois funções como main , Py_Main e (todas as) outras estão disponíveis; chamá-los pode ter efeitos desastrosos (no programa atual)
      • Isso também não se aplica ao Win (mas isso não é grande coisa, pois o msvcrt.dll está localizado em "% SystemRoot% \ System32", que está em % PATH% por padrão). Eu queria levar as coisas adiante e replicar esse comportamento no Win (e enviar um patch), mas, como se vê, [MS.Docs]: a função GetProcAddress apenas "vê" símbolos exportados , portanto, a menos que alguém declare as funções no executável principal como __declspec(dllexport)(por que diabos a pessoa comum faria isso?), o programa principal é carregável, mas praticamente inutilizável
  5. Instale 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.

  6. 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 :

      (py35x64_test) e:\Work\Dev\StackOverflow\q000082831>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\System32\\cmd.exe\" > nul 2>&1'))"
      0
      
      (py35x64_test) e:\Work\Dev\StackOverflow\q000082831>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\System32\\cmd.exe.notexist\" > nul 2>&1'))"
      1
    • Nix ( Lnx ( Ubtu )):

      [cfati@cfati-ubtu16x64-0:~]> python3 -c "import os; print(os.system('ls \"/tmp\" > /dev/null 2>&1'))"
      0
      [cfati@cfati-ubtu16x64-0:~]> python3 -c "import os; print(os.system('ls \"/tmp.notexist\" > /dev/null 2>&1'))"
      512

Bottom line :

  • Fazer uso try / exceto / pessoa / finalmente blocos, porque eles podem impedi-lo correr em uma série de problemas desagradáveis. Um contra-exemplo em que posso pensar é o desempenho: esses blocos são caros, portanto, tente não colocá-los no código que deve ser executado centenas de milhares de vezes por segundo (mas, como na maioria dos casos, envolve acesso ao disco, não será o caso).

Nota (s) final (is) :

  • Vou tentar mantê-lo atualizado, todas as sugestões são bem-vindas, vou incorporar qualquer coisa útil que venha à resposta
CristiFati
fonte
3
Você pode elaborar essa afirmação? "Embora não seja uma boa prática, estou usando os.F_OK na chamada, mas isso é apenas para fins de clareza (o valor é 0)"
sk8asd123
6
@ sk8asd123: É meio difícil fazê-lo em um comentário: geralmente, é melhor usar constantes com funções com as quais elas se juntam. Isso se aplica ao trabalhar com vários módulos que definem a mesma constante, porque alguns podem não estar atualizados e é melhor que as funções e constantes estejam sincronizadas. Ao trabalhar com ctypes (chamando as funções diretamente), eu deveria ter definido a constante (do MSDN ) ou não usar uma constante. É apenas uma diretriz que eu uso, em 99,9% provavelmente não faz diferença (funcionalmente).
19417 CristiFati
3
@CristiFati: A partir de 3.6, glob.iglob(e glob.globtambé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ê usar globmétodos sem curingas, a função é inteligente: ela sabe que você pode ter apenas um hit, simplificando o globbing para apenas os.path.isdirouos.path.lexists (dependendo se o caminho termina /).
ShadowRanger 29/11
3
Essa segunda parte do meu comentário (globbing sem curinga não realmente itera a pasta, e nunca o fez) significa que é uma solução perfeitamente eficiente para o problema (mais lento do que ligar diretamente os.path.isdirou os.path.lexistuma 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).
ShadowRanger 29/11
154

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.

import os
fname = "foo.txt"
if os.path.isfile(fname):
    print("file does exist at this time")
else:
    print("no such file exists at this time")
un33k
fonte
17
Desde que você pretenda acessar o arquivo, a condição de corrida existe , independentemente de como seu programa é construído. Seu programa não pode garantir que outro processo no computador não tenha modificado o arquivo. É o que Eric Lippert se refere como uma exceção exógena . Você não pode evitá-lo, verificando a existência do arquivo com antecedência.
Isaac Supeene
@IsaacSupeene A melhor prática é fazer com que a janela de operação (arquivo) tão pequeno quanto possível seguido por um tratamento de exceção adequada
un33k
145

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:

import pathlib
p = pathlib.Path('path/to/file')
if p.is_file():  # or p.is_dir() to see if it is a directory
    # do stuff

Você pode (e geralmente deve) ainda usar um try/exceptbloco ao abrir arquivos:

try:
    with p.open() as f:
        # do awesome stuff
except OSError:
    print('Well darn.')

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:

# installs pathlib2 on older Python versions
# the original third-party module, pathlib, is no longer maintained.
pip install pathlib2

Importe-o da seguinte maneira:

# Older Python versions
import pathlib2 as pathlib
Cody Piersall
fonte
124

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:

pkoch
fonte
3
Adicione fontes melhores para apoiar sua declaração.
BlueTrin
11
O link Evitar condições de corrida (suporte para Apple Dev) mencionado não suporta sua resposta. Trata-se apenas do uso de arquivos temporários que contêm informações confidenciais em sistemas operacionais mal projetados que não protegem adequadamente arquivos / diretórios temporários por meio de permissões restritas. O uso try...exceptnão ajuda a resolver esse problema de qualquer maneira.
jstine
O problema com esse método é que, se você tiver um pedaço de código importante, dependendo do arquivo não existir, colocá-lo na 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.)
Camion
119

Como verifico se existe um arquivo, usando Python, sem usar uma instrução try?

Agora disponível desde o Python 3.4, importe e instancie um Pathobjeto com o nome do arquivo e verifique o is_filemétodo (observe que isso retorna True para links simbólicos que também apontam para arquivos regulares):

>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False

Se você estiver no Python 2, poderá fazer o backport do módulo pathlib a partir do pypi pathlib2, ou verificar isfileno os.pathmódulo:

>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False

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 usa tryem toda parte em sua implementação.

Como o Python usa em tryqualquer 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 Pathobjeto em pathlib. Note que isso .existsnão está certo, porque diretórios não são arquivos (exceto no sentido unix de que tudo é um arquivo).

>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True

Então, precisamos usar is_file:

>>> root.is_file()
False

Aqui está a ajuda sobre is_file:

is_file(self)
    Whether this path is a regular file (also True for symlinks pointing
    to regular files).

Então, vamos pegar um arquivo que sabemos que é um arquivo:

>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True

Por padrão, NamedTemporaryFileexclui o arquivo quando fechado (e será fechado automaticamente quando não houver mais referências a ele).

>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False

Se você se aprofundar na implementação , verá que is_fileusa try:

def is_file(self):
    """
    Whether this path is a regular file (also True for symlinks pointing
    to regular files).
    """
    try:
        return S_ISREG(self.stat().st_mode)
    except OSError as e:
        if e.errno not in (ENOENT, ENOTDIR):
            raise
        # Path doesn't exist or is a broken symlink
        # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
        return False

Condições da corrida: Por que gostamos de tentar

Gostamos tryporque evita as condições da corrida. Com try, 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 trydeclaração usando o suppressgerenciador de contexto.

Evitando condições de corrida sem uma declaração de tentativa: suppress

O Python 3.4 nos fornece o suppressgerenciador de contexto (anteriormente o ignoregerenciador de contexto), que semanticamente faz exatamente a mesma coisa em menos linhas, enquanto também (pelo menos superficialmente) atende à solicitação original para evitar uma trydeclaração:

from contextlib import suppress
from pathlib import Path

Uso:

>>> with suppress(OSError), Path('doesnotexist').open() as f:
...     for line in f:
...         print(line)
... 
>>>
>>> with suppress(OSError):
...     Path('doesnotexist').unlink()
... 
>>> 

Para Pythons anteriores, você poderia fazer o seu próprio suppress, mas sem um tryserá mais detalhado do que com. Eu acredito que essa é realmente a única resposta que não usa tryem nenhum nível no Python que possa ser aplicada antes do Python 3.4, porque ele usa um gerenciador de contexto:

class suppress(object):
    def __init__(self, *exceptions):
        self.exceptions = exceptions
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is not None:
            return issubclass(exc_type, self.exceptions)

Talvez mais fácil com uma tentativa:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass

Outras opções que não atendem à solicitação "sem tentativa":

isfile

import os
os.path.isfile(path)

dos documentos :

os.path.isfile(path)

Retorne True se path for um arquivo regular existente. Isso segue links simbólicos, portanto, ambos islink()e isfile()podem ser verdadeiros para o mesmo caminho.

Mas se você examinar a fonte dessa função, verá que ela realmente usa uma instrução try:

# This follows symbolic links, so both islink() and isdir() can be true
# for the same path on systems that support symlinks
def isfile(path):
    """Test whether a path is a regular file"""
    try:
        st = os.stat(path)
    except os.error:
        return False
    return stat.S_ISREG(st.st_mode)
>>> OSError is os.error
True

Tudo o que está fazendo é usar o caminho fornecido para ver se ele pode obter estatísticas, capturar OSErrore 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:

try:
    with open(path) as f:
        f.read()
except OSError:
    pass

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:

import os
os.access(path, os.F_OK)

Também sofre dos mesmos problemas de condição de corrida que isfile. Dos documentos :

Nota: O uso de access () para verificar se um usuário está autorizado a, por exemplo, abrir um arquivo antes de fazê-lo usando open () cria uma falha de segurança, porque o usuário pode explorar o curto intervalo de tempo entre verificar e abrir o arquivo para manipulá-lo. É preferível usar técnicas de EAFP. Por exemplo:

if os.access("myfile", os.R_OK):
    with open("myfile") as fp:
        return fp.read()
return "some default data"

é melhor escrito como:

try:
    fp = open("myfile")
except IOError as e:
    if e.errno == errno.EACCES:
        return "some default data"
    # Not a permission error.
    raise
else:
    with fp:
        return fp.read()

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:

Pessoalmente, prefiro este porque, sob o capô, ele chama APIs nativas (via "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), mas também abre uma porta para possíveis erros do usuário, e não é tão Pythonic quanto outras variantes :

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 (incluindo KeyboardInterrupteSystemExit !) Passem silenciosamente, o que é uma boa maneira de ocultar bugs.

Isso parece incentivar os usuários a adotar práticas inadequadas.

Aaron Hall
fonte
87
import os
#Your path here e.g. "C:\Program Files\text.txt"
#For access purposes: "C:\\Program Files\\text.txt"
if os.path.exists("C:\..."):   
    print "File found!"
else:
    print "File not found!"

A importação osfacilita 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.

Atlas
fonte
9
Esta resposta está errada. os.path.existsretorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadas os.path.isfile.
21430 Chris Johnson
84

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:

insira a descrição da imagem aqui

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)

>>> import os
>>> path = "path to a word document"
>>> os.path.isfile(path)
True
>>> os.path.splitext(path)[1] == ".docx" # test if the extension is .docx
True
Tom Fuller
fonte
72

Em 2016, a melhor maneira ainda está usando os.path.isfile:

>>> os.path.isfile('/path/to/some/file.txt')

Ou no Python 3 você pode usar pathlib:

import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
    ...
KaiBuxe
fonte
3
Posso perguntar: Qual é a vantagem de usar o módulo 'pathlib' em vez do módulo 'os' em python3 para esta verificação?
Joko 25/02
3
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.
KaiBuxe
65

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

try:
    f = open(filepath)
except IOError:
    print 'Oh dear.'

Mas se você quiser renomear um arquivo, se ele existir, e, portanto, não precisar abri-lo, faça

if os.path.isfile(filepath):
    os.rename(filepath, filepath + '.old')

Se você deseja gravar em um arquivo, se ele não existir, faça

# python 2
if not os.path.isfile(filepath):
    f = open(filepath, 'w')

# python 3, x opens for exclusive creation, failing if the file already exists
try:
    f = open(filepath, 'wx')
except IOError:
    print 'file already exists'

Se você precisar de bloqueio de arquivos, isso será diferente.

Chade
fonte
3
Esta resposta está errada. os.path.existsretorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadas os.path.isfile.
22420 Chris Johnson
6
No seu terceiro exemplo, eu crio um link nomeado filepathcom o tempo certo, e BAM , você substitui o arquivo de destino. Você deve fazer open(filepath, 'wx')em um try...exceptbloco para evitar o problema.
espectros
1
No seu segundo exemplo, pelo menos no Windows, você receberá um OSErrorse filepath + '.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 ".
Tom Myddeltyn
@ TomMyddeltyn: A partir do Python 3.3,os.replace realiza uma substituição silenciosa do arquivo de destino (é idêntico ao os.renamecomportamento 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.
ShadowRanger 29/11
No renameexemplo: ainda deve ser feito com try/ except. os.rename(ou os.replaceno 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
ShadowRanger 29/11
59

Você pode tentar isso (mais seguro):

try:
    # http://effbot.org/zone/python-with-statement.htm
    # 'with' is safer to open a file
    with open('whatever.txt') as fh:
        # Do something with 'fh'
except IOError as e:
    print("({})".format(e))

A saída seria:

([Erro 2] Não existe esse arquivo ou diretório: 'Whatever.txt')

Então, dependendo do resultado, seu programa pode continuar em execução a partir daí ou você pode codificar para pará-lo, se desejar.

philberndt
fonte
18
A pergunta original pediu uma solução que não usatry
RRS
5
Essa resposta perde o objetivo do OP. Verificar se existe um arquivo não é o mesmo que verificar se você pode abri-lo. Haverá casos em que um arquivo existe, mas por vários motivos, você não pode abri-lo.
21716 Chris Johnson
51

Embora eu sempre recomende usar trye exceptinstruções, aqui estão algumas possibilidades para você (meu favorito pessoal é usar os.access):

  1. Tente abrir o arquivo:

    A abertura do arquivo sempre verificará a existência do arquivo. Você pode criar uma função da seguinte maneira:

    def File_Existence(filepath):
        f = open(filepath)
        return True

    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 trydeclaração exceto `assim (obrigado a hsandt por me fazer pensar):

    def File_Existence(filepath):
        try:
            f = open(filepath)
        except IOError, OSError: # Note OSError is for later versions of Python
            return False
    
        return True
  2. 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.

    import os.path
    >>> os.path.exists("this/is/a/directory")
    True
    >>> os.path.exists("this/is/a/file.txt")
    True
    >>> os.path.exists("not/a/directory")
    False
  3. 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:

    >>> import os
    >>> os.access("/is/a/file.txt", os.F_OK)
    True

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 deniedou no such file or directory. Se você pegar um IOError, defina o IOError as e(como minha primeira opção) e digite print(e.args)para que você possa determinar o problema. Espero que ajude! :)

Zizouz212
fonte
51

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:

import os
os.path.isfile('~/file.md')  # Returns True if exists, else False
# additionaly check a dir
os.path.isdir('~/folder')  # Returns True if the folder exists, else False
# check either a dir or a file
os.path.exists('~/file')

Fiz uma folha de dicas exaustiva para sua referência:

#os.path methods in exhaustive cheatsheet
{'definition': ['dirname',
               'basename',
               'abspath',
               'relpath',
               'commonpath',
               'normpath',
               'realpath'],
'operation': ['split', 'splitdrive', 'splitext',
               'join', 'normcase'],
'compare': ['samefile', 'sameopenfile', 'samestat'],
'condition': ['isdir',
              'isfile',
              'exists',
              'lexists'
              'islink',
              'isabs',
              'ismount',],
 'expand': ['expanduser',
            'expandvars'],
 'stat': ['getatime', 'getctime', 'getmtime',
          'getsize']}
Cálculo
fonte
37

Se o arquivo for para abrir, você poderá usar uma das seguintes técnicas:

with open('somefile', 'xt') as f: #Using the x-flag, Python3.3 and above
    f.write('Hello\n')

if not os.path.exists('somefile'): 
    with open('somefile', 'wt') as f:
        f.write("Hello\n")
else:
    print('File already exists!')

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.

bergercookie
fonte
9
Esta resposta está errada. os.path.existsretorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadas os.path.isfile.
22420 Chris Johnson
também tenho o problema do falso positivo.
Zorglub29
docs.python.org/3/library/os.path.html#os.path.exists Para a declaração acima de chris >> os.path.exists (path)> Return True se path se referir a um caminho existente ou a um diretório aberto descritor de arquivo. Retorna False para links simbólicos quebrados. Em algumas plataformas, essa função pode retornar False se a permissão não for concedida para executar os.stat () no arquivo solicitado, mesmo que o caminho exista fisicamente. Alterado na versão 3.3: o caminho agora pode ser um número inteiro: True será retornado se for um descritor de arquivo aberto, caso contrário, False. Alterado na versão 3.6: Aceita um objeto semelhante a um caminho.
precisa saber é o seguinte
36

Além disso, os.access():

if os.access("myfile", os.R_OK):
    with open("myfile") as fp:
        return fp.read()

Sendo R_OK, W_OKe X_OKas bandeiras para testar permissões ( doc ).

zgoda
fonte
20
if os.path.isfile(path_to_file):
    try: 
        open(path_to_file)
            pass
    except IOError as e:
        print "Unable to open file"

Criar exceções é considerado uma abordagem aceitável e pitônica para controle de fluxo em seu programa. Considere manipular arquivos ausentes com IOErrors. Nessa situação, uma exceção IOError será gerada se o arquivo existir, mas o usuário não tiver permissões de leitura.

SRC: http://www.pfinn.net/python-check-if-file-exists.html

CONvid19
fonte
3
O OP perguntou como verificar se existe um arquivo. É possível que um arquivo exista, mas você não poderá abri-lo. Portanto, usar a abertura de um arquivo como proxy para verificar se o arquivo existe não está correto: terá falsos negativos.
Chris Johnson
19

Se você importou NumPy já para outros fins, então não há necessidade de importar outras bibliotecas, como pathlib, os, paths, etc.

import numpy as np
np.DataSource().exists("path/to/your/file")

Isso retornará verdadeiro ou falso com base em sua existência.

durjoy
fonte
18

Você pode escrever a sugestão de Brian sem o try:.

from contextlib import suppress

with suppress(IOError), open('filename'):
    process()

suppressfaz parte do Python 3.4. Em versões mais antigas, você pode escrever rapidamente sua própria supressão:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass
Chris
fonte
17

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 Popenpara acessar find. No entanto, se você estiver no Windows, ele se replica findcom um andador eficiente do sistema de arquivos.

O código em si não usa um trybloco ... exceto para determinar o sistema operacional e, assim, direcioná-lo para o estilo "Unix" findou para o manual find. Os testes de tempo mostraram que o processo de trydeterminação do sistema operacional foi mais rápido, então eu usei um lá (mas em nenhum outro lugar).

>>> import pox
>>> pox.find('*python*', type='file', root=pox.homedir(), recurse=False)
['/Users/mmckerns/.python']

E o doc…

>>> print pox.find.__doc__
find(patterns[,root,recurse,type]); Get path to a file or directory

    patterns: name or partial name string of items to search for
    root: path string of top-level directory to search
    recurse: if True, recurse down from root directory
    type: item filter; one of {None, file, dir, link, socket, block, char}
    verbose: if True, be a little verbose about the search

    On some OS, recursion can be specified by recursion depth (an integer).
    patterns can be specified with basic pattern matching. Additionally,
    multiple patterns can be specified by splitting patterns with a ';'
    For example:
        >>> find('pox*', root='..')
        ['/Users/foo/pox/pox', '/Users/foo/pox/scripts/pox_launcher.py']

        >>> find('*shutils*;*init*')
        ['/Users/foo/pox/pox/shutils.py', '/Users/foo/pox/pox/__init__.py']

>>>

A implementação, se você preferir, está aqui: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190

Mike McKerns
fonte
17

Verifique se existe arquivo ou diretório

Você pode seguir estas três maneiras:

Nota1: os.path.isfileUtilizado apenas para arquivos

import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists

Nota2: O os.path.existsusado para arquivos e diretórios

import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists

O pathlib.Pathmétodo (incluído no Python 3+, instalável com pip para Python 2)

from pathlib import Path
Path(filename).exists()
Ali Hallaji
fonte
16

Adicionando mais uma ligeira variação que não é exatamente refletida nas outras respostas.

Isso manipulará o caso do file_pathser Noneou da sequência vazia.

def file_exists(file_path):
    if not file_path:
        return False
    elif not os.path.isfile(file_path):
        return False
    else:
        return True

Adicionando uma variante com base na sugestão do Shahbaz

def file_exists(file_path):
    if not file_path:
        return False
    else:
        return os.path.isfile(file_path)

Adicionando uma variante com base na sugestão de Peter Wood

def file_exists(file_path):
    return file_path and os.path.isfile(file_path):
Marcel Wilson
fonte
3
if (x) return true; else return false;é realmente justo return x. Suas últimas quatro linhas podem se tornar return os.path.isfile(file_path). Enquanto estamos nisso, toda a função pode ser simplificada como return file_path and os.path.isfile(file_path).
Shahbaz
Você tem que ter cuidado com return xno caso de if (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.
Marcel Wilson
1
Verdade. Nesse caso, no entanto, xé os.path.isfile(..)assim que já é booleano.
Shahbaz
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.
Marcel Wilson
3
return file_path and os.path.isfile(file_path)
Peter Wood
15

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.

python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"

Espero que isto seja útil.

Amor e paz - Joe Codeswell
fonte
6
Verificação em uma linha no bash: [ -f "${file}" ] && echo "file found" || echo "file not found"(que é igual a if [ ... ]; then ...; else ...; fi).
Flotzilla
12

Você pode usar a biblioteca "OS" do Python:

>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
Pradip Das
fonte
5
Esta resposta está errada. os.path.existsretorna true para itens que não são arquivos, como diretórios. Isso dá falsos positivos. Veja as outras respostas recomendadas os.path.isfile.
22420 Chris Johnson
@ Chris Johnson, a função os.path.exists () verifica se existe um caminho no sistema. PATH pode ser um DIRETÓRIO ou ARQUIVO. Funcionará bem em ambos os casos. Por favor, tente com algum exemplo
Pradip Das
Então, essa resposta funciona. Ótimo. Se o caminho não é o de um arquivo. Era sobre isso que se tratava? Não.
Debosmit Ray
Depende. Se o objetivo de determinar a existência de um "arquivo" é descobrir se o caminho já existe (e, portanto, não é um caminho em que novos dados podem ser armazenados sem excluir outras informações), tudo existsbem. 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).
starturtle 5/09/17
12

Como verifico se existe um arquivo sem usar a instrução try?

Em 2016, essa ainda é a maneira mais fácil de verificar se existe um arquivo e se é um arquivo:

import os
os.path.isfile('./file.txt')    # Returns True if exists, else False

isfileé realmente apenas um método auxiliar que usa internamente os.state stat.S_ISREG(mode)por baixo. Este os.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 aqui

Nota: 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 ifinstruções ( apenas um conselho ).

Inconnu
fonte
9
import os.path

def isReadableFile(file_path, file_name):
    full_path = file_path + "/" + file_name
    try:
        if not os.path.exists(file_path):
            print "File path is invalid."
            return False
        elif not os.path.isfile(full_path):
            print "File does not exist."
            return False
        elif not os.access(full_path, os.R_OK):
            print "File cannot be read."
            return False
        else:
            print "File can be read."
            return True
    except IOError as ex:
        print "I/O error({0}): {1}".format(ex.errno, ex.strerror)
    except Error as ex:
        print "Error({0}): {1}".format(ex.errno, ex.strerror)
    return False
#------------------------------------------------------

path = "/usr/khaled/documents/puzzles"
fileName = "puzzle_1.txt"

isReadableFile(path, fileName)
Khaled.K
fonte
@ j6m8 sim, isReadableFile(path,fileName)vai voltar Truese o arquivo está acessível e legível pelo processo \ Programas \ fio
Khaled.K