7012

How do I check whether a file exists or not, without using the try statement?

syntagma
  • 23,346
  • 16
  • 78
  • 134
spence91
  • 77,143
  • 9
  • 27
  • 19

40 Answers40

6425

If the reason you're checking is so you can do something like if file_exists: open_it(), it's safer to use a try around the attempt to open it. Checking and then opening risks the file being deleted or moved or something between when you check and when you try to open it.

If you're not planning to open the file immediately, you can use os.path.isfile

Return True if path is an existing regular file. This follows symbolic links, so both islink() and isfile() can be true for the same path.

import os.path
os.path.isfile(fname) 

if you need to be sure it's a file.

Starting with Python 3.4, the pathlib module offers an object-oriented approach (backported to pathlib2 in Python 2.7):

from pathlib import Path

my_file = Path("/path/to/file")
if my_file.is_file():
    # file exists

To check a directory, do:

if my_file.is_dir():
    # directory exists

To check whether a Path object exists independently of whether is it a file or directory, use exists():

if my_file.exists():
    # path exists

You can also use resolve(strict=True) in a try block:

try:
    my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
    # doesn't exist
else:
    # exists
Georgy
  • 12,464
  • 7
  • 65
  • 73
rslite
  • 81,705
  • 4
  • 44
  • 47
  • 83
    concerning the first remark (use "try" if check before open) unfortunately this will not work if you want to open for appending being sure it exists before since 'a' mode will create if not exists. – makapuf Jun 20 '18 at 07:58
  • 18
    Note that `FileNotFoundError` was introduced in Python 3. If you also need to support Python 2.7 as well as Python 3, you can use `IOError` instead (which `FileNotFoundError` subclasses) https://stackoverflow.com/a/21368457/1960959 – scottclowe Mar 29 '19 at 13:44
  • 19
    @makapuf You can open it for "updating" (`open('file', 'r+')`) and then seek to the end. – kyrill Apr 30 '19 at 17:45
  • 2
    Wait, so `pathlib2` < `pathlib`? `pathlib` is for python3, right? I've been using `pathlib2` thinking it was superior. – theX Jul 02 '20 at 21:26
  • 3
    @kyrill: Opening a file for appending is not the same as opening it for writing and seeking to the end: When you have concurrent writers, they will overwrite each other without `'a'`. – hagello Nov 20 '20 at 14:48
  • 2
    @makapuf So? The intention is to write to the file, appending if it already exists, creating it if it doesn't. Your objection doesn't make sense. – user207421 May 11 '21 at 04:09
  • @theX yes, the packages are very confusingly named. – Nesha25 Oct 02 '21 at 23:41
  • Be aware that the FileNotFoundError exception was added in Python 3. If you require compatibility with both Python 2.7 and Python 3, you can utilize the IOError exception instead, as it is a superclass of FileNotFoundError. – Dmitrii Malygin May 17 '23 at 12:21
  • 1
    @DmitriiMalygin: this is already mentioned in a comment above by scottclowe (second comment of this anwser at the time I am writing). – Arkane May 19 '23 at 13:35
  • A common mistake is to check for `Path(foo).exists`, which is _always_ true (because `exists` is a function and lazy-evaluates to `True` when put in a conditional this way). You probably meant to do this: `Path(foo).exists()`. – carl.anderson Jul 19 '23 at 16:15
2580

Use os.path.exists to check both files and directories:

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

Use os.path.isfile to check only files (note: follows symbolic links):

os.path.isfile(file_path)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PierreBdR
  • 42,120
  • 10
  • 46
  • 62
1211

Unlike isfile(), exists() will return True for directories. So depending on if you want only plain files or also directories, you'll use isfile() or exists(). Here is some simple REPL output:

>>> 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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bortzmeyer
  • 34,164
  • 12
  • 67
  • 91
873
import os

if os.path.isfile(filepath):
   print("File exists")
Iacchus
  • 2,671
  • 2
  • 29
  • 24
Paul
  • 18,349
  • 7
  • 49
  • 56
422

Use os.path.isfile() with 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")
null
  • 1,944
  • 1
  • 14
  • 24
Yugal Jindle
  • 44,057
  • 43
  • 129
  • 197
  • 74
    having multiple conditions, some of which are superfluous, is _less_ clear and explicit. – wim Apr 09 '13 at 05:45
  • 18
    It is also redundant. If the file doesn't exist, `os.access()` will return false. – user207421 Mar 13 '18 at 00:01
  • 11
    @EJP In linux files can exist but not accesible. – e-info128 Jul 16 '18 at 21:30
  • 12
    since you `import os`, you do not need to `import os.path` again as it is already part of `os`. You just need to import `os.path` if you are only going to use functions from `os.path` and not from `os` itself, to import a smaller thing, but as you use `os.access` and `os.R_OK`, the second import is not needed. – Jester Aug 24 '18 at 13:10
  • 6
    Checking if the user has access rights to read the file is very professional. Often data is on local drive during dev, and on network share in prod. Then this might lead to such a situation. Also, the code is perfectly clear and readable and explicit. – Martin Meeser Jul 02 '20 at 07:04
357
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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
benefactual
  • 7,079
  • 5
  • 23
  • 16
302

Although almost every possible way has been listed in (at least one of) the existing answers (e.g. Python 3.4 specific stuff was added), I'll try to group everything together.

Note: every piece of Python standard library code that I'm going to post, belongs to version 3.5.3.

Problem statement:

  1. Check file (arguable: also folder ("special" file) ?) existence

  2. Don't use try / except / else / finally blocks

Possible solutions:

1. [Python.Docs]: os.path.exists(path)

Also check other function family members like os.path.isfile, os.path.isdir, os.path.lexists for slightly different behaviors:

Return True if path refers to an existing path or an open file descriptor. Returns False for broken symbolic links. On some platforms, this function may return False if permission is not granted to execute os.stat() on the requested file, even if the path physically exists.

All good, but if following the import tree:

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

    • genericpath.py - line ~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
      

it's just a try / except block around [Python.Docs]: os.stat(path, *, dir_fd=None, follow_symlinks=True). So, your code is try / except free, but lower in the framestack there's (at least) one such block. This also applies to other functions (including os.path.isfile).

1.1. [Python.Docs]: pathlib - Path.is_file()
  • It's a fancier (and more [Wiktionary]: Pythonic) way of handling paths, but

  • Under the hood, it does exactly the same thing (pathlib.py - line ~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.Docs]: With Statement Context Managers

Either:

  • Create one:

    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)
            # Only swallow FileNotFoundError (not e.g. TypeError - if the user passes a wrong argument like None or float or ...)
            return exc_type in Swallow.swallowed_exceptions
    
    • And its usage - I'll replicate the os.path.isfile behavior (note that this is just for demonstrating purposes, do not attempt to write such code for production):

      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.Docs]: contextlib.suppress(*exceptions) - which was specifically designed for selectively suppressing exceptions


But, they seem to be wrappers over try / except / else / finally blocks, as [Python.Docs]: Compound statements - The with statement states:

This allows common try...except...finally usage patterns to be encapsulated for convenient reuse.

3. Filesystem traversal functions

Search the results for matching item(s):

  1. [Python.Docs]: os.listdir(path='.') (or [Python.Docs]: os.scandir(path='.') on Python v3.5+, backport: [PyPI]: scandir)

    Using scandir() instead of listdir() can significantly increase the performance of code that also needs file type or file attribute information, because os.DirEntry objects expose this information if the operating system provides it when scanning a directory. All os.DirEntry methods may perform a system call, but is_dir() and is_file() usually only require a system call for symbolic links; os.DirEntry.stat() always requires a system call on Unix, but only requires one for symbolic links on Windows.

  2. [Python.Docs]: os.walk(top, topdown=True, onerror=None, followlinks=False)

    • Uses os.listdir (os.scandir when available)
  3. [Python.Docs]: glob.iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False, include_hidden=False) (or its predecessor: glob.glob)

    • Doesn't seem a traversing function per se (at least in some cases), but it still uses os.listdir


Since these iterate over folders, (in most of the cases) they are inefficient for our problem (there are exceptions, like non wildcarded globbing - as @ShadowRanger pointed out), so I'm not going to insist on them. Not to mention that in some cases, filename processing might be required.

4. [Python.Docs]: os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True)

Its behavior is close to os.path.exists (actually it's wider, mainly because of the 2nd argument).

  • User permissions might restrict the file "visibility" as the doc states:

    ... test if the invoking user has the specified access to path. mode should be F_OK to test the existence of path...

  • Security considerations:

    Using access() to check if a user is authorized to e.g. open a file before actually doing so using open() creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it.

os.access("/tmp", os.F_OK)

Since I also work in C, I use this method as well because under the hood, it calls native APIs (again, via "${PYTHON_SRC_DIR}/Modules/posixmodule.c"), but it also opens a gate for possible user errors, and it's not as Pythonic as other variants. So, don't use it unless you know what you're doing:

  • Nix: [Man7]: ACCESS(2)

    Warning: Using these calls to check if a user is authorized to, for example, open a file before actually doing so using open(2) creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it. For this reason, the use of this system call should be avoided.

  • Win: [MS.Learn]: GetFileAttributesW function (fileapi.h)

As seen, this approach is highly discouraged (especially on Nix).

Note: calling native APIs is also possible via [Python.Docs]: ctypes - A foreign function library for Python, but in most cases it's more complicated. Before working with CTypes, check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) out.

(Win specific): since vcruntime###.dll (msvcr###.dll for older VStudio versions - I'm going to refer to it as UCRT) exports a [MS.Learn]: _access, _waccess function family as well, here's an example (note that the recommended [Python.Docs]: msvcrt - Useful routines from the MS VC++ runtime doesn't export them):

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 ctypes as cts, os
>>> cts.CDLL("msvcrt")._waccess(u"C:\\Windows\\Temp", os.F_OK)
0
>>> cts.CDLL("msvcrt")._waccess(u"C:\\Windows\\Temp.notexist", os.F_OK)
-1

Notes:


The Linux (Ubuntu ([Wikipedia]: Ubuntu version history) 16 x86_64 (pc064)) counterpart as well:

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 ctypes as cts, os
>>> cts.CDLL("/lib/x86_64-linux-gnu/libc.so.6").access(b"/tmp", os.F_OK)
0
>>> cts.CDLL("/lib/x86_64-linux-gnu/libc.so.6").access(b"/tmp.notexist", os.F_OK)
-1

Notes:

  • Instead hardcoding libc.so (LibC)'s path ("/lib/x86_64-linux-gnu/libc.so.6") which may (and most likely, will) vary across systems, None (or the empty string) can be passed to CDLL constructor (ctypes.CDLL(None).access(b"/tmp", os.F_OK)). According to [Man7]: DLOPEN(3):

    If filename is NULL, then the returned handle is for the main program. When given to dlsym(3), this handle causes a search for a symbol in the main program, followed by all shared objects loaded at program startup, and then all shared objects loaded by dlopen() with the flag RTLD_GLOBAL.

  • Main (current) program (python) is linked against LibC, so its symbols (including access) will be loaded

  • This has to be handled with care, since functions like main, Py_Main and (all the) others are available; calling them could have disastrous effects (on the current program)

  • This doesn't also apply to Windows (but that's not such a big deal, since UCRT is located in "%SystemRoot%\System32" which is in %PATH% by default). I wanted to take things further and replicate this behavior on Windows (and submit a patch), but as it turns out, [MS.Learn]: GetProcAddress function (libloaderapi.h) only "sees" exported symbols, so unless someone declares the functions in the main executable as __declspec(dllexport) (why on Earth the common person would do that?), the main program is loadable, but it is pretty much unusable

5. 3rd-party modules with filesystem capabilities

Most likely, will rely on one of the ways above (maybe with slight customizations).
One example would be (again, Win specific) [GitHub]: mhammond/pywin32 - Python for Windows (pywin32) Extensions, which is a Python wrapper over WinAPIs.

But, since this is more like a workaround, I'm stopping here.

6. SysAdmin approach

I consider this a (lame) workaround (gainarie): use Python as a wrapper to execute shell commands:

  • Win:

    (py35x64_test) [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q000082831]> "e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\Temp\" > nul 2>&1'))"
    0
    
    (py35x64_test) [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q000082831]> "e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\Temp.notexist\" > nul 2>&1'))"
    1
    
  • Nix ([Wikipedia]: Unix-like) - Ubuntu:

    [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q000082831]> python3 -c "import os; print(os.system('ls \"/tmp\" > /dev/null 2>&1'))"
    0
    [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q000082831]> python3 -c "import os; print(os.system('ls \"/tmp.notexist\" > /dev/null 2>&1'))"
    512
    

Bottom line:

  • Do use try / except / else / finally blocks, because they can prevent you running into a series of nasty problems

  • A possible counterexample that I can think of, is performance: such blocks are costly, so try not to place them in code that it's supposed to run hundreds of thousands times per second (but since (in most cases) it involves disk access, it won't be the case)

CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • 7
    @sk8asd123: Kind of hard to doo it in a comment: generally, it's best to use constants with functions that they come together with. That applies when working with multiple modules that define the same constant, because some might not be up to date, and it's best for the functions and constants to be in sync. When working with *ctypes* (calling the functions directly) I should have defined the constant (from *MSDN*), or not use a constant at all. It's just a guideline that I use, in 99.9% it probably makes no difference (functionally). – CristiFati Nov 19 '17 at 23:54
  • 4
    @CristiFati: As of 3.6, [`glob.iglob` (and `glob.glob` as well) are based on `os.scandir`](https://docs.python.org/3/whatsnew/3.6.html#optimizations), so it's lazy now; to get the first hit in a directory of 10M files, you only scan until you reach the first hit. And even pre-3.6, if you use `glob` methods w/o any wildcards, the function is smart: It knows you can only have one hit, so [it simplifies the globbing to just `os.path.isdir` or `os.path.lexists`](https://github.com/python/cpython/blob/3ae41554c69b807659fab815ad5675bed5ae237/Lib/glob.py#L41) (depending on whether path ends in `/`). – ShadowRanger Nov 29 '17 at 18:29
  • 4
    That second part of my comment (non-wildcarded globbing doesn't actually iterate the folder, and never has) does mean it's a perfectly efficient solution to the problem (slower than directly calling `os.path.isdir` or `os.path.lexist` since it's a bunch of Python level function calls and string operations before it decides the efficient path is viable, but no additional system call or I/O work, which is orders of magnitude slower). – ShadowRanger Nov 29 '17 at 18:38
220

Python 3.4+ has an object-oriented path module: pathlib. Using this new module, you can check whether a file exists like this:

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

You can (and usually should) still use a try/except block when opening files:

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

The pathlib module has lots of cool stuff in it: convenient globbing, checking file's owner, easier path joining, etc. It's worth checking out. If you're on an older Python (version 2.6 or later), you can still install pathlib with pip:

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

Then import it as follows:

# Older Python versions
import pathlib2 as pathlib
Honest Abe
  • 8,430
  • 4
  • 49
  • 64
Cody Piersall
  • 8,312
  • 2
  • 43
  • 57
  • You can use [`pathlib.Path.exists`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.exists), which covers more cases than `is_file` – Ryan Haining Oct 11 '20 at 21:13
174

This is the simplest way to check if a file exists. Just because the file existed when you checked doesn't guarantee that it will be there when you need to open it.

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")
MrWonderful
  • 2,530
  • 1
  • 16
  • 22
Val Neekman
  • 17,692
  • 14
  • 63
  • 66
  • 18
    As long as you intend to access the file, the race condition _does exist_, regardless of how your program is constructed. Your program cannot guarantee that another process on the computer has not modified the file. It's what Eric Lippert refers to as an [exogenous exception](http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx). You cannot avoid it by checking for the file's existence beforehand. – Isaac Supeene Nov 23 '14 at 18:37
  • 1
    @IsaacSupeene Best practice is to make the window of (file) operation as small as possible followed by a proper exception handling – Val Neekman Jul 28 '18 at 02:52
  • The best would be to open the file, using try+catch and there is no time window. – Anders Lindén Aug 31 '21 at 08:50
144

How do I check whether a file exists, using Python, without using a try statement?

Now available since Python 3.4, import and instantiate a Path object with the file name, and check the is_file method (note that this returns True for symlinks pointing to regular files as well):

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

If you're on Python 2, you can backport the pathlib module from pypi, pathlib2, or otherwise check isfile from the os.path module:

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

Now the above is probably the best pragmatic direct answer here, but there's the possibility of a race condition (depending on what you're trying to accomplish), and the fact that the underlying implementation uses a try, but Python uses try everywhere in its implementation.

Because Python uses try everywhere, there's really no reason to avoid an implementation that uses it.

But the rest of this answer attempts to consider these caveats.

Longer, much more pedantic answer

Available since Python 3.4, use the new Path object in pathlib. Note that .exists is not quite right, because directories are not files (except in the unix sense that everything is a file).

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

So we need to use is_file:

>>> root.is_file()
False

Here's the help on is_file:

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

So let's get a file that we know is a file:

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

By default, NamedTemporaryFile deletes the file when closed (and will automatically close when no more references exist to it).

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

If you dig into the implementation, though, you'll see that is_file uses 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

Race Conditions: Why we like try

We like try because it avoids race conditions. With try, you simply attempt to read your file, expecting it to be there, and if not, you catch the exception and perform whatever fallback behavior makes sense.

If you want to check that a file exists before you attempt to read it, and you might be deleting it and then you might be using multiple threads or processes, or another program knows about that file and could delete it - you risk the chance of a race condition if you check it exists, because you are then racing to open it before its condition (its existence) changes.

Race conditions are very hard to debug because there's a very small window in which they can cause your program to fail.

But if this is your motivation, you can get the value of a try statement by using the suppress context manager.

Avoiding race conditions without a try statement: suppress

Python 3.4 gives us the suppress context manager (previously the ignore context manager), which does semantically exactly the same thing in fewer lines, while also (at least superficially) meeting the original ask to avoid a try statement:

from contextlib import suppress
from pathlib import Path

Usage:

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

For earlier Pythons, you could roll your own suppress, but without a try will be more verbose than with. I do believe this actually is the only answer that doesn't use try at any level in the Python that can be applied to prior to Python 3.4 because it uses a context manager instead:

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)

Perhaps easier with a try:

from contextlib import contextmanager

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

Other options that don't meet the ask for "without try":

isfile

import os
os.path.isfile(path)

from the docs:

os.path.isfile(path)

Return True if path is an existing regular file. This follows symbolic links, so both islink() and isfile() can be true for the same path.

But if you examine the source of this function, you'll see it actually does use a try statement:

# 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

All it's doing is using the given path to see if it can get stats on it, catching OSError and then checking if it's a file if it didn't raise the exception.

If you intend to do something with the file, I would suggest directly attempting it with a try-except to avoid a race condition:

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

os.access

Available for Unix and Windows is os.access, but to use you must pass flags, and it does not differentiate between files and directories. This is more used to test if the real invoking user has access in an elevated privilege environment:

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

It also suffers from the same race condition problems as isfile. From the docs:

Note: Using access() to check if a user is authorized to e.g. open a file before actually doing so using open() creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it. It’s preferable to use EAFP techniques. For example:

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

is better written as:

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

Avoid using os.access. It is a low level function that has more opportunities for user error than the higher level objects and functions discussed above.

Criticism of another answer:

Another answer says this about os.access:

Personally, I prefer this one because under the hood, it calls native APIs (via "${PYTHON_SRC_DIR}/Modules/posixmodule.c"), but it also opens a gate for possible user errors, and it's not as Pythonic as other variants:

This answer says it prefers a non-Pythonic, error-prone method, with no justification. It seems to encourage users to use low-level APIs without understanding them.

It also creates a context manager which, by unconditionally returning True, allows all Exceptions (including KeyboardInterrupt and SystemExit!) to pass silently, which is a good way to hide bugs.

This seems to encourage users to adopt poor practices.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
142

Prefer the try statement. It's considered better style and avoids race conditions.

Don't take my word for it. There's plenty of support for this theory. Here's a couple:

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pkoch
  • 2,682
  • 1
  • 19
  • 17
  • 4
    Please add better sources to support your statement. – BlueTrin Sep 10 '15 at 09:09
  • 12
    The cited Avoiding Race Conditions (apple dev support) link does not support your answer. It concerns only using temporary files that contain sensitive information on poorly designed operating systems that don't properly sandbox temporary files / directories via restricted permissions. Using `try...except` doesn't help resolve *that* problem anyway. – jstine Sep 28 '15 at 15:38
  • The problem with this method, is that if you have an important piece of code depending on the file not existing, putting it in the `except:` clause will make that an exception arising in this part of your code will raise a confusing message (second error raised during the processing of the first one.) – Camion May 24 '19 at 10:43
  • But one typically opens files with context managers, and plenty of packages don't seem to implement them with terribly good exceptions. E.g. xarray just throws a super generic "ValueError" with some confusing message about the backend if you try to open say a folder instead of a netcdf file. Catching a ValueError here could mask all sorts of other problems. – Ben Farmer May 25 '23 at 00:08
105

Use:

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!"

Importing os makes it easier to navigate and perform standard actions with your operating system.

For reference, also see How do I check whether a file exists without exceptions?.

If you need high-level operations, use shutil.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
incalite
  • 3,077
  • 3
  • 26
  • 32
  • 15
    This answer is wrong. `os.path.exists` returns true for things that aren't files, such as directories. This gives false positives. See the other answers that recommend `os.path.isfile`. – Chris Johnson Aug 01 '15 at 13:56
101

Testing for files and folders with os.path.isfile(), os.path.isdir() and os.path.exists()

Assuming that the "path" is a valid path, this table shows what is returned by each function for files and folders:

enter image description here

You can also test if a file is a certain type of file using os.path.splitext() to get the extension (if you don't already know it)

>>> 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
  • 5,291
  • 7
  • 33
  • 42
97

TL;DR
The answer is: use the pathlib module


Pathlib is probably the most modern and convenient way for almost all of the file operations. For the existence of a file or a folder a single line of code is enough. If file is not exists, it will not throw any exception.

from pathlib import Path

if Path("myfile.txt").exists(): # works for both file and folders
    # do your cool stuff...

The pathlib module was introduced in Python 3.4, so you need to have Python 3.4+. This library makes your life much easier while working with files and folders, and it is pretty to use. Here is more documentation about it: pathlib — Object-oriented filesystem paths.

BTW, if you are going to reuse the path, then it is better to assign it to a variable.

So it will become:

from pathlib import Path

p = Path("loc/of/myfile.txt")
if p.exists(): # works for both file and folders
    # do stuffs...
#reuse 'p' if needed.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Memin
  • 3,788
  • 30
  • 31
  • 6
    Be aware that this returns True if the file is not present but path to file exists. If you are really interested in asking whether the file exists or not you should be using p.is_file() – bravhek Jun 25 '21 at 21:38
  • 1
    @bravhek I think your comment is confusing. What do you mean by 'path to file'? If you mean 'path to dir', and if the directory exists, then of course it works as it should. The OP said `p.exists()` works for both files and folders. – starriet Mar 13 '23 at 02:25
  • @starriet, The question is about the existence of the file, however p.exists() will return a false positive when the folder containing the checked file exists but the file itself doesn't. – Bravhek Mar 14 '23 at 10:50
  • @Bravhek, can you please give an example to better highlight the issue, I may also update my answer accordingly, to better inform the users. Thank you. – Memin Mar 14 '23 at 14:19
  • @Memin, suppose you want to check if the file "myfile.txt", exists in folder "c:\temp". if you declare fpath = Path(r"c:\temp\myfile.txt"), and then check for fpath.exists(), it will return True but the file does not exists! (false positive)... in contrast fpath.is_file() will return false, wich is the desired output. – Bravhek Mar 14 '23 at 19:09
  • @Bravhek I'm not sure if I've understood this correctly. I tried creating a temporary file inside the '/tmp' directory using the example code at https://onecompiler.com/python/3z2ntw9r9, and when I checked for the existence of the file, it returned True as expected. Similarly, when I searched for a file that did not exist, it returned False as expected. Could you please provide some sample code that I can use to test your explanation? Thank you. – Memin Mar 14 '23 at 23:34
84

In 2016 the best way is still using os.path.isfile:

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

Or in Python 3 you can use pathlib:

import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
    ...
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
KaiBuxe
  • 908
  • 7
  • 8
  • 4
    `pathlib` is python's OOP solution for paths. You can do a lot more with it. If you just need to check existance, the advantage is not so big. – KaiBuxe Feb 25 '16 at 10:44
77

It doesn't seem like there's a meaningful functional difference between try/except and isfile(), so you should use which one makes sense.

If you want to read a file, if it exists, do

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

But if you just wanted to rename a file if it exists, and therefore don't need to open it, do

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

If you want to write to a file, if it doesn't exist, do

# 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'

If you need file locking, that's a different matter.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
chad
  • 1,339
  • 12
  • 10
  • 5
    This answer is wrong. `os.path.exists` returns true for things that aren't files, such as directories. This gives false positives. See the other answers that recommend `os.path.isfile`. – Chris Johnson Aug 01 '15 at 13:54
  • 6
    On your third example, I create a link named `filepath` with the right timing, and *BAM*, you overwrite the target file. You should do `open(filepath, 'wx')` in a `try...except` block to avoid the issue. – spectras Aug 24 '15 at 14:05
  • 1
    In your second example, at least in Windows, you will get an `OSError` if `filepath + '.old'` already exists: "On Windows, if dst already exists, OSError will be raised even if it is a file; there may be no way to implement an atomic rename when dst names an existing file." – Tom Myddeltyn May 24 '16 at 14:14
  • @TomMyddeltyn: [As of Python 3.3, `os.replace`](https://docs.python.org/3/library/os.html#os.replace) portably performs silent replacement of the destination file (it's identical to `os.rename`'s Linux behavior) (it only errors if the destination name exists and is a directory). So you're stuck on 2.x, but Py3 users have had a good option for several years now. – ShadowRanger Nov 29 '17 at 18:14
  • On the `rename` example: It should still be done with `try`/`except`. `os.rename` (or `os.replace` on modern Python) is atomic; making it check then rename introduces an unnecessary race and additional system calls. Just do `try: os.replace(filepath, filepath + '.old') except OSError: pass` – ShadowRanger Nov 29 '17 at 18:17
67

You could try this (safer):

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

The ouput would be:

([Errno 2] No such file or directory: 'whatever.txt')

Then, depending on the result, your program can just keep running from there or you can code to stop it if you want.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
philberndt
  • 1,118
  • 2
  • 11
  • 15
  • 22
    The original question asked for a solution that does not use `try` – rrs Apr 23 '14 at 13:10
  • 8
    This answer misses the point of the OP. Checking is a file exists is not the same as checking if you can open it. There will be cases where a file does exist but for a variety of reasons, you can't open it. – Chris Johnson Feb 17 '16 at 18:52
56

Date: 2017-12-04

Every possible solution has been listed in other answers.

An intuitive and arguable way to check if a file exists is the following:

import os

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

# Additionally, check a directory
os.path.isdir('~/folder')  # Returns True if the folder exists, else False

# Check either a directory or a file
os.path.exists('~/file')

I made an exhaustive cheat sheet for your reference:

# os.path methods in exhaustive cheat sheet
{'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']}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
AbstProcDo
  • 19,953
  • 19
  • 81
  • 138
54

Although I always recommend using try and except statements, here are a few possibilities for you (my personal favourite is using os.access):

  1. Try opening the file:

    Opening the file will always verify the existence of the file. You can make a function just like so:

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

    If it's False, it will stop execution with an unhanded IOError or OSError in later versions of Python. To catch the exception, you have to use a try except clause. Of course, you can always use a try except` statement like so (thanks to hsandt for making me think):

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

    This will check the existence of what you specify. However, it checks for files and directories so beware about how you use it.

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

    This will check whether you have access to the file. It will check for permissions. Based on the os.py documentation, typing in os.F_OK, it will check the existence of the path. However, using this will create a security hole, as someone can attack your file using the time between checking the permissions and opening the file. You should instead go directly to opening the file instead of checking its permissions. (EAFP vs LBYP). If you're not going to open the file afterwards, and only checking its existence, then you can use this.

    Anyway, here:

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

I should also mention that there are two ways that you will not be able to verify the existence of a file. Either the issue will be permission denied or no such file or directory. If you catch an IOError, set the IOError as e (like my first option), and then type in print(e.args) so that you can hopefully determine your issue. I hope it helps! :)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zizouz212
  • 4,908
  • 5
  • 42
  • 66
44

If the file is for opening you could use one of the following techniques:

with open('somefile', 'xt') as f: # Using the x-flag, Python 3.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!')

Note: This finds either a file or a directory with the given name.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bergercookie
  • 2,542
  • 1
  • 30
  • 38
  • 10
    This answer is wrong. `os.path.exists` returns true for things that aren't files, such as directories. This gives false positives. See the other answers that recommend `os.path.isfile`. – Chris Johnson Aug 01 '15 at 13:55
  • got the false positive problem also. – Zorglub29 May 19 '18 at 21:33
  • https://docs.python.org/3/library/os.path.html#os.path.exists **To the above statement from chris** >>os.path.exists(path) > Return True if path refers to an existing path or an open file descriptor. Returns False for broken symbolic links. On some platforms, this function may return False if permission is not granted to execute os.stat() on the requested file, even if the path physically exists. Changed in version 3.3: path can now be an integer: True is returned if it is an open file descriptor, False otherwise. Changed in version 3.6: Accepts a path-like object. – JayRizzo Aug 31 '18 at 23:24
41

Additionally, os.access():

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

Being R_OK, W_OK, and X_OK the flags to test for permissions (doc).

armatita
  • 12,825
  • 8
  • 48
  • 49
zgoda
  • 12,775
  • 4
  • 37
  • 46
26
if os.path.isfile(path_to_file):
    try:
        open(path_to_file)
            pass
    except IOError as e:
        print "Unable to open file"

Raising exceptions is considered to be an acceptable, and Pythonic, approach for flow control in your program. Consider handling missing files with IOErrors. In this situation, an IOError exception will be raised if the file exists but the user does not have read permissions.

Source: Using Python: How To Check If A File Exists

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
  • 6
    The OP asked how to check if a file exists. It's possible for a file to exist but for you to not be able to open it. Therefore using opening a file as a proxy for checking if the file exists is not correct: will have false negatives. – Chris Johnson Feb 17 '16 at 18:58
23

Check file or directory exists

You can follow these three ways:

1. Using isfile()

Note 1: The os.path.isfile used only for files

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

2. Using exists

Note 2: The os.path.exists is used for both files and directories

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

3. The pathlib.Path method (included in Python 3+, installable with pip for Python 2)

from pathlib import Path
Path(filename).exists()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ali Hallaji
  • 3,712
  • 2
  • 29
  • 36
22

If you imported NumPy already for other purposes then there is no need to import other libraries like pathlib, os, paths, etc.

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

This will return true or false based on its existence.

JayRizzo
  • 3,234
  • 3
  • 33
  • 49
durjoy
  • 1,709
  • 1
  • 14
  • 25
20

You can write Brian's suggestion without the try:.

from contextlib import suppress

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

suppress is part of Python 3.4. In older releases you can quickly write your own suppress:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chris
  • 2,461
  • 1
  • 23
  • 29
19

Here's a one-line Python command for the Linux command line environment. I find this very handy since I'm not such a hot Bash guy.

python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 9
    One-line check in bash: `[ -f "${file}" ] && echo "file found" || echo "file not found"` (which is the same as `if [ ... ]; then ...; else ...; fi`). – flotzilla Oct 01 '15 at 07:48
  • 2
    Python would be a completely wrong tool for this job on the command line. – ruohola Oct 25 '21 at 10:54
  • Hi @ruohola :) I disagree. – Love and peace - Joe Codeswell Oct 26 '21 at 18:11
  • 1
    [On one-liners](https://stackoverflow.com/questions/6167127/how-to-put-multiple-statements-in-one-line/6167353#6167353) in Python: *"...which makes Python close to useless for command-line one-liner programs ... You can get away with a sequence of simple statements, separated by semi-colon ... as soon as you add a construct that introduces an indented block (like if), you need the line break..."* – Peter Mortensen Oct 04 '22 at 20:08
19

I'm the author of a package that's been around for about 10 years, and it has a function that addresses this question directly. Basically, if you are on a non-Windows system, it uses Popen to access find. However, if you are on Windows, it replicates find with an efficient filesystem walker.

The code itself does not use a try block… except in determining the operating system and thus steering you to the "Unix"-style find or the hand-buillt find. Timing tests showed that the try was faster in determining the OS, so I did use one there (but nowhere else).

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

And the 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']

>>>

The implementation, if you care to look, is here: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike McKerns
  • 33,715
  • 8
  • 119
  • 139
17

Adding one more slight variation which isn't exactly reflected in the other answers.

This will handle the case of the file_path being None or empty string.

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

Adding a variant based on suggestion from Shahbaz

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

Adding a variant based on suggestion from Peter Wood

def file_exists(file_path):
    return file_path and os.path.isfile(file_path):
Marcel Wilson
  • 3,842
  • 1
  • 26
  • 55
  • 4
    `if (x) return true; else return false;` is really just `return x`. Your last four lines can become `return os.path.isfile(file_path)`. While we're at it, the whole function can be simplified as `return file_path and os.path.isfile(file_path)`. – Shahbaz Jan 04 '17 at 22:50
  • You have to be careful with `return x` in the case of `if (x)`. Python will consider an empty string False in which case we would be returning an empty string instead of a bool. The purpose of this function is to always return bool. – Marcel Wilson Jan 05 '17 at 17:08
  • 1
    True. In this case however, `x` is `os.path.isfile(..)` so it's already bool. – Shahbaz Jan 05 '17 at 17:10
  • `os.path.isfile(None)` raises an exception which is why I added the if check. I could probably just wrap it in a try/except instead but I felt it was more explicit this way. – Marcel Wilson Jan 05 '17 at 17:13
  • 4
    `return file_path and os.path.isfile(file_path)` – Peter Wood Apr 06 '17 at 10:35
15

How do I check whether a file exists, without using the try statement?

In 2016, this is still arguably the easiest way to check if both a file exists and if it is a file:

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

isfile is actually just a helper method that internally uses os.stat and stat.S_ISREG(mode) underneath. This os.stat is a lower-level method that will provide you with detailed information about files, directories, sockets, buffers, and more. More about os.stat here

Note: However, this approach will not lock the file in any way and therefore your code can become vulnerable to "time of check to time of use" (TOCTTOU) bugs.

So raising exceptions is considered to be an acceptable, and Pythonic, approach for flow control in your program. And one should consider handling missing files with IOErrors, rather than if statements (just an advice).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Taufiq Rahman
  • 5,600
  • 2
  • 36
  • 44
14

You can use the "OS" library of Python:

>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pradip Das
  • 728
  • 1
  • 7
  • 16
  • 6
    This answer is wrong. `os.path.exists` returns true for things that aren't files, such as directories. This gives false positives. See the other answers that recommend `os.path.isfile`. – Chris Johnson Aug 01 '15 at 13:55
  • @Chris Johnson , os.path.exists() function checks whether a path exists in system. PATH may be a DIRECTORY or FILE. It will work fine on both the cases. Please try with some example – Pradip Das Aug 02 '15 at 14:51
  • So, this answer works. Great. **Iff** the path isn't that of a file. Is that what the question was about? No. – Debosmit Ray Apr 14 '16 at 23:33
  • It depends. If the goal of determining the existence of a "file" is to find out whether the path already exists (and is therefore not a path where new data can be stored without deleting other information), then `exists` is fine. If the goal is to determine whether it's safe to open a presumably existing file, then the criticism is justified and exists is not precise enough. Sadly, the OP doesn't specify which is the desired goal (and probably won't do so any more). – starturtle Sep 05 '17 at 11:24
10
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)
bubble
  • 3
  • 2
Khaled.K
  • 5,828
  • 1
  • 33
  • 51
  • @j6m8 yes, `isReadableFile(path,fileName)` will return `True` if the file is reachable and readable by the process\program\thread – Khaled.K Aug 09 '15 at 07:46
10

exists() and is_file() methods of 'Path' object can be used for checking if a given path exists and is a file.

Python 3 program to check if a file exists:

# File name:  check-if-file-exists.py

from pathlib import Path

filePath = Path(input("Enter path of the file to be found: "))

if filePath.exists() and filePath.is_file():
    print("Success: File exists")
else:
    print("Error: File does not exist")

Output:

$ python3 check-if-file-exists.py

Enter path of the file to be found: /Users/macuser1/stack-overflow/index.html

Success: File exists

$ python3 check-if-file-exists.py

Enter path of the file to be found: hghjg jghj

Error: File does not exist

Gopinath
  • 4,066
  • 1
  • 14
  • 16
9

Use os.path.exists() to check whether file exists or not:

def fileAtLocation(filename,path):
    return os.path.exists(path + filename)
 

filename="dummy.txt"
path = "/home/ie/SachinSaga/scripts/subscription_unit_reader_file/"


if fileAtLocation(filename,path):
   print('file found at location..')
else:
   print('file not found at location..')
syntagma
  • 23,346
  • 16
  • 78
  • 134
Devbrat Shukla
  • 504
  • 4
  • 11
  • Any clarification on why this answer is downvoted? Is os.path.exists() not a solution? – Yash Nag Sep 28 '20 at 22:51
  • 3
    @YashNag [from another answer](https://stackoverflow.com/a/84173/843953): Unlike `isfile()`, `exists()` will return True for directories. – Pranav Hosangadi Sep 30 '20 at 14:44
  • 1
    This is usually what you want, not isfile, since the question "does a file exist" is usually really asking whether a path exists, not whether it's a file. Please stop downvoting useful information. – Glenn Maynard Feb 11 '21 at 00:31
  • Why are you replacing spaces in the filename? You could now be checking whether a different file exists than the one being asked about. Why are you calling str() on it? If it's not already a string defining the file there's probably something very wrong with how the function is being called. – Ceisc Mar 11 '21 at 22:21
  • 1
    @GlennMaynard - No, you check for file existence because you want to do something with the file (maybe read it, maybe create one). Having a like-named directory is a problem. You usually want to test both to avoid bugs. – tdelaney Sep 15 '21 at 06:54
  • Thank you @GlennMaynard for explaining :) – Devbrat Shukla Jun 24 '22 at 07:13
7

To check if a file exists,

from sys import argv

from os.path import exists
script, filename = argv
target = open(filename)
print "file exists: %r" % exists(filename)
Hanson
  • 193
  • 2
  • 10
7
import os
path = /path/to/dir

root,dirs,files = os.walk(path).next()
if myfile in files:
   print "yes it exists"

This is helpful when checking for several files. Or you want to do a set intersection/ subtraction with an existing list.

Chillar Anand
  • 27,936
  • 9
  • 119
  • 136
Jesvin Jose
  • 22,498
  • 32
  • 109
  • 202
  • 4
    This is wrong on two counts: (1) `os.walk` find all files under a directory tree -- if the user wants to check for `./FILE`, it's unlikely he'd want to treat `./some/sub/folder/FILE` as a match, which your solution does; and (2) your solution is very inefficient compared to a simple `os.path.isfile()` call in the case where there are many files below the current directory. In the case where no matching filename-without-path exists within the tree, your code will enumerate every single file in the tree before returning false. – Chris Johnson Jun 13 '17 at 22:10
6

You can use the following open method to check if a file exists + readable:

file = open(inputFile, 'r')
file.close()
Zaheer
  • 402
  • 6
  • 20
6

You can use os.listdir to check if a file is in a certain directory.

import os
if 'file.ext' in os.listdir('dirpath'):
    #code
iPhynx
  • 443
  • 6
  • 11
6

Use:

import os

# For testing purposes the arguments defaulted to the current folder and file.
# returns True if file found
def file_exists(FOLDER_PATH='../', FILE_NAME=__file__):
    return os.path.isdir(FOLDER_PATH) \
        and os.path.isfile(os.path.join(FOLDER_PATH, FILE_NAME))

It is basically a folder check, and then a file check with the proper directory separator using os.path.join.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
4

Another possible option is to check whether the filename is in the directory using os.listdir():

import os
if 'foo.txt' in os.listdir():
    # Do things

This will return true if it is and false if not.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
IsraelW
  • 63
  • 9
  • This could fail if the OS is case-insensitive, as in MS-Windows, because the actual file name could be 'Foo.TXT'. Using pathlib solves this problem (because it compares Path objects using the OS conventions) : `if Path('foo.txt') in Path().iterdir()`. – Niccolo M. Jul 28 '22 at 08:15
0

This is how I found a list of files (in these images) in one folder and searched it in a folder (with subfolders):

# This script concatenates JavaScript files into a unified JavaScript file to reduce server round-trips

import os
import string
import math
import ntpath
import sys

#import pyodbc

import gzip
import shutil

import hashlib

# BUF_SIZE is totally arbitrary, change for your app!
BUF_SIZE = 65536  # Let’s read stuff in 64 kilobyte chunks

# Iterate over all JavaScript files in the folder and combine them
filenames = []
shortfilenames = []

imgfilenames = []
imgshortfilenames = []

# Get a unified path so we can stop dancing with user paths.
# Determine where files are on this machine (%TEMP% directory and application installation directory)
if '.exe' in sys.argv[0]: # if getattr(sys, 'frozen', False):
    RootPath = os.path.abspath(os.path.join(__file__, "..\\"))

elif __file__:
    RootPath = os.path.abspath(os.path.join(__file__, "..\\"))

print ("\n storage of image files RootPath: %s\n" %RootPath)

FolderPath = "D:\\TFS-FARM1\\StoneSoup_STS\\SDLC\\Build\\Code\\StoneSoup_Refactor\\StoneSoupUI\\Images"
print ("\n storage of image files in folder to search: %s\n" %FolderPath)

for root, directories, filenames2 in os.walk(FolderPath):
    for filename in filenames2:
        fullname = os.path.join(root, filename)
        filenames.append(fullname)
        shortfilenames.append(filename)

for i, fname in enumerate(shortfilenames):
        print("%s - %s" % (i+1, fname))

for root, directories, filenames2 in os.walk(RootPath):
    for filename in filenames2:
        fullname = os.path.join(root, filename)
        imgfilenames.append(fullname)
        imgshortfilenames.append(filename)

for i, fname in enumerate(imgshortfilenames):
        print("%s - %s" % (i+1, fname))

for i, fname in enumerate(imgshortfilenames):
        if fname in shortfilenames:
            print("%s - %s exists" % (i+1, fname))
        else:
            print("%s - %s ABSENT" % (i+1, fname))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ban_Midou
  • 25
  • 4