How do I check whether a file exists or not, without using the try
statement?
my_path.exists()
.
my_path.exists()
is not sufficient. my_path.is_file()
will tell you if its a file (could be good for reading). But if you want to create the file, you also have to check exists
so exclude directories or other non-file things in the file system that will cause the fail.
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
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 symlinks):
os.path.isfile(file_path)
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
import os
if os.path.isfile(filepath):
print("File exists")
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")
os.access()
will return false.
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.
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
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:
Check file (arguable: also folder ("special" file) ?) existence Don't use try / except / else / finally blocks
Possible solutions:
[Python 3]: os.path.exists(path) (also check other function family members like os.path.isfile, os.path.isdir, os.path.lexists for slightly different behaviors) 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. 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 3]: 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 funcs (including os.path.isfile). 1.1. [Python 3]: Path.is_file() It's a fancier (and more 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 [Python 3]: 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) 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 ...) 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 3]: 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 3]: The with statement states: This allows common try...except...finally usage patterns to be encapsulated for convenient reuse. Filesystem traversal functions (and search the results for matching item(s)) [Python 3]: os.listdir(path='.') (or [Python 3]: os.scandir(path='.') on Python v3.5+, backport: [PyPI]: scandir) Under the hood, both use: Nix: [man7]: OPENDIR(3) / [man7]: READDIR(3) / [man7]: CLOSEDIR(3) Win: [MS.Docs]: FindFirstFileW function / [MS.Docs]: FindNextFileW function / [MS.Docs]: FindClose function via [GitHub]: python/cpython - (master) cpython/Modules/posixmodule.c 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. [Python 3]: os.walk(top, topdown=True, onerror=None, followlinks=False) It uses os.listdir (os.scandir when available) [Python 3]: glob.iglob(pathname, *, recursive=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. [Python 3]: os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True) whose 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... 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, as @AaronHall rightly pointed out, don't use it unless you know what you're doing: Nix: [man7]: ACCESS(2) (!!! pay attention to the note about the security hole its usage might introduce !!!) Win: [MS.Docs]: GetFileAttributesW function Note: calling native APIs is also possible via [Python 3]: ctypes - A foreign function library for Python, but in most cases it's more complicated. (Win specific): Since vcruntime* (msvcr*) .dll exports a [MS.Docs]: _access, _waccess function family as well, here's an example: 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 Notes: Although it's not a good practice, I'm using os.F_OK in the call, but that's just for clarity (its value is 0) I'm using _waccess so that the same code works on Python3 and Python2 (in spite of unicode related differences between them) Although this targets a very specific area, it was not mentioned in any of the previous answers The Lnx (Ubtu (16 x64)) 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 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 Notes: Instead hardcoding 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(), 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 Win (but that's not such a big deal, since msvcrt.dll is located in "%SystemRoot%\System32" which is in %PATH% by default). I wanted to take things further and replicate this behavior on Win (and submit a patch), but as it turns out, [MS.Docs]: GetProcAddress function only "sees" exported symbols, so unless someone declares the functions in the main executable as __declspec(dllexport) (why on Earth the regular person would do that?), the main program is loadable but pretty much unusable Install some third-party module 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. Another (lame) workaround (gainarie) is (as I like to call it,) the sysadmin approach: use Python as a wrapper to execute shell commands Win: (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:
Do use try / except / else / finally blocks, because they can prevent you running into a series of nasty problems. A counter-example 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).
Final note(s):
I will try to keep it up to date, any suggestions are welcome, I will incorporate anything useful that will come up into the answer
glob.iglob
(and glob.glob
as well) are based on os.scandir
, 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
(depending on whether path ends in /
).
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).
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
pathlib.Path.exists
, which covers more cases than is_file
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")
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.
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:
Style: Section "Handling unusual conditions" of http://allendowney.com/sd/notes/notes11.txt
Avoiding Race Conditions
try...except
doesn't help resolve that problem anyway.
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.)
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 to check whether a file exists using Python?
If you need high-level operations, use shutil
.
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
.
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:
https://i.stack.imgur.com/tOs9p.png
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
TL;DR
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.
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 lib makes your life much easier while working with files and folders and it is pretty to use, here is more doc about it (https://docs.python.org/3/library/pathlib.html).
BTW, if you are going to reuse the path, then it is better to assign it to a variable
so 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.
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():
...
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.
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.
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
.
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.
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."
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.
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
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.
try
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
# 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')
I made an exhaustive cheatsheet for your reference:
#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']}
Although I always recommend using try
and except
statements, here are a few possibilities for you (my personal favourite is using os.access
):
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 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 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! :)
If the file is for opening you could use one of the following techniques:
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!')
UPDATE
Just to avoid confusion and based on the answers I got, current answer finds either a file or a directory with the given name.
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
.
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).
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.
SRC: http://www.pfinn.net/python-check-if-file-exists.html
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.
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
Check file or directory exists
You can follow these three ways:
Note1: 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
Note2: The os.path.exists 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
The pathlib.Path method (included in Python 3+, installable with pip for Python 2)
from pathlib import Path
Path(filename).exists()
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):
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)
.
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.
x
is os.path.isfile(..)
so it's already bool.
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.
return file_path and os.path.isfile(file_path)
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
Here's a 1 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')"
I hope this is helpful.
[ -f "${file}" ] && echo "file found" || echo "file not found"
(which is the same as if [ ... ]; then ...; else ...; fi
).
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
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
.
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).
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).
Success story sharing
FileNotFoundError
was introduced in Python 3. If you also need to support Python 2.7 as well as Python 3, you can useIOError
instead (whichFileNotFoundError
subclasses) stackoverflow.com/a/21368457/1960959open('file', 'r+')
) and then seek to the end.pathlib2
<pathlib
?pathlib
is for python3, right? I've been usingpathlib2
thinking it was superior.'a'
.