如何使用Python检查文件是否存在?

如何检查文件是否存在,而不使用try语句?

如果你正在检查的原因是你可以做一些事情,如if file_exists: open_it() ,试图打开它是更安全的。 检查然后打开文件被删除或移动的风险,或者当您检查和尝试打开文件时。

如果你不打算立即打开文件,你可以使用os.path.isfile

如果path是现有的常规文件,则返回True 。 这遵循符号链接,所以islink()和isfile()对于相同的path可以是true。

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

如果你需要确定它是一个文件。

从Python 3.4开始, pathlib模块提供了一个面向对象的方法(在Python 2.7中pathlib2移植到pathlib2 ):

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

要检查目录,请执行以下操作:

 if my_file.is_dir(): # directory exists 

要检查一个Path对象是否独立于文件或目录是否exists() ,使用exists()

 if my_file.exists(): # path exists 

你也可以在try块中使用resolve()

 try: my_abs_path = my_file.resolve(): except FileNotFoundError: # doesn't exist else: # exists 

你有os.path.exists函数:

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

这对文件和目录都返回True ,但你可以使用os.path.isfile来testing它是否是一个文件。 它遵循符号链接。

isfile()不同, exists()将为目录返回True
因此,根据您是否只需要纯文件或目录,您将使用isfile()exists() 。 这是一个简单的REPL输出。

 >>> print os.path.isfile("/etc/password.txt") True >>> print os.path.isfile("/etc") False >>> print os.path.isfile("/does/not/exist") False >>> print os.path.exists("/etc/password.txt") True >>> print os.path.exists("/etc") True >>> print os.path.exists("/does/not/exist") False 
 import os.path if os.path.isfile(filepath): 

使用os.path.isfile()os.access()

 import os import os.path PATH='./file.txt' if os.path.isfile(PATH) and os.access(PATH, os.R_OK): print "File exists and is readable" else: print "Either file is missing or is not readable" 
 import os os.path.exists(path) # returns whether the path (dir or file) exists or not os.path.isfile(path) # returns whether the file exists or not 

这是检查文件是否存在的最简单的方法。 仅仅因为文件在您选中时存在并不能保证您需要打开文件。

 import os fname = "foo.txt" if os.path.isfile(fname): print("file does exist at this time") else: print("no such file") 

喜欢try语句。 这被认为是更好的风格,避免了竞赛条件。

不要拿我的话来说。 这个理论有很多支持。 这里有一对夫妇:

  • 样式: http ://allendowney.com/sd/notes/notes11.txt中的“处理exception情况”部分
  • 避免种族条件

Python 3.4有一个面向对象的path模块: pathlib 。 使用这个新模块,你可以检查一个文件是否像这样存在:

 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 

打开文件时,您可以(通常应该)仍然使用try/except块:

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

pathlib模块中有很多很酷的东西:方便的通配符,检查文件的所有者,更容易的pathjoin等,值得检查。 如果您使用的是较旧的Python(版本2.6或更高版本),则仍然可以使用pip安装pathlib:

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

然后导入它如下:

 # Older Python versions import pathlib2 as pathlib 
 import os #Your path here eg "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!" 

通过导入os ,可以更轻松地导航并使用操作系统执行标准操作。

另请参阅如何使用Python检查文件是否存在?

如果您需要高级操作,请使用shutil

如何使用Python检查文件是否存在,而不使用try语句?

在Python 3.4中,使用pathlib的新Path对象。

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

所以让我们得到一个我们知道是一个文件的文件:

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

默认情况下, NamedTemporaryFile在closures时删除文件(并且在没有更多的引用存在时会自动closures)。

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

如果你深入实现,你会看到is_file使用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 

没有一个尝试声明:

压制

Python 3.4为我们提供了suppress上下文pipe理器(以前是ignore上下文pipe理器),它在less量行中语义上完全相同的事情,同时(至less在表面上)满足原始请求以避免try语句:

 from contextlib import suppress with suppress(OSError), open(path) as f: f.read() 

用法:

 >>> with suppress(OSError), open('doesnotexist') as f: ... f.read() ... >>> 

对于较早的python,你可以推出自己的suppress ,但是没有try就会比使用更为冗长。 我相信这实际上是唯一的答案,不使用任何可以在Python 3.4之前应用的级别 ,因为它使用上下文pipe理器:

 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) 

更容易一试:

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

其他选项不符合要求“没有尝试”:

ISFILE

 import os os.path.isfile(path) 

从文档 :

os.path.isfile(path)

如果path是现有的常规文件,则返回True。 这遵循符号链接,所以islink()isfile()对于相同的path可以是true。

但是如果你检查这个函数的来源 ,你会发现它实际上使用了一个try语句:

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

它所做的就是使用给定的path来查看是否可以获得统计信息,捕获OSError ,然后检查是否是文件,如果没有引发exception。

如果你打算对这个文件做些什么,我会build议你直接尝试一下,除了避免竞争条件:

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

os.access

可用于Unix和Windows的是os.access ,但使用您必须传递标志,并且不区分文件和目录。 这更用于testing真正的调用用户是否可以在提升的特权环境中访问:

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

它也遭受与文件相同的竞争条件问题。 从文档 :

注意:在使用open()之前,使用access()检查用户是否有权例如打开一个文件,因为用户可能会利用检查和打开文件之间的短时间间隔来操作它。 最好使用EAFP技术。 例如:

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

最好写成:

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

使用os.path.isfile()os.path.isdir()os.path.exists()testing文件和文件夹。

假设“path”是一个有效的path,该表显示了每个函数对文件和文件夹返回的内容:

在这里输入图像描述

你也可以使用os.path.splitext()来testing一个文件是否是某种types的文件来获得扩展名(如果你还不知道的话)

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

try / except和isfile()之间似乎没有有意义的function差异,所以您应该使用哪一个有意义。

如果你想读一个文件,如果它存在,那么

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

但是如果你只是想重命名一个文件,所以不需要打开它

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

如果你想写一个文件,如果它不存在,那么

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

如果你需要文件locking,那是另外一回事。

在2016年最好的方法是仍然使用os.path.isfile

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

或者在Python 3中,您可以使用pathlib

 import pathlib path = pathlib.Path('/path/to/some/file.txt') if path.is_file(): ... 

你可以试试这个(更安全):

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

输出将是:

([Errno 2]没有这样的文件或目录:'whatever.txt')

然后,根据结果,您的程序可以继续从那里运行,或者您可以编写代码来停止它,如果你想。

尽pipe我总是推荐使用tryexcept语句,但是这里有一些可能性(我个人最喜欢使用os.access ):

  1. 尝试打开文件:

    打开文件将始终validation文件的存在。 你可以像这样做一个函数:

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

    如果它是False,那么在更高版本的Python中,将会停止执行,而不会引起IOError或OSError。 要捕捉exception,你必须使用一个try除了从句。 当然,你总是可以try除了这样的陈述(感谢hsandt让我想):

     def File_Existence(filepath): try: f = open(filepath) except IOError, OSError: # Note OSError is for later versions of Python return False return True 
  2. 使用os.path.exists(path)

    这将检查您指定的内容。 但是,它检查文件目录,所以要小心你如何使用它。

     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. 使用os.access(path, mode)

    这将检查您是否有权访问该文件。 它会检查权限。 根据os.py文档,键入os.F_OK ,它将检查path的存在。 但是,使用这将会产生一个安全漏洞,因为用户可以利用检查权限和打开文件之间的时间来攻击你的文件。 您应该直接打开文件而不是检查其权限。 ( EAFP vs LBYP )。 如果你以后不打开文件,只检查它的存在,那么你可以使用它。

    无论如何,在这里:

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

我还应该提到有两种方法你将无法validation文件的存在。 无论是问题将被permission deniedno such file or directory 。 如果你发现IOError ,把IOError as e设置IOError as e (就像我的第一个选项),然后inputprint(e.args)这样就可以确定你的问题了。 我希望它有帮助! 🙂

2017/11/03

虽然我认为所有可能的方法都已经被列入(至less是其中一个)现有的答案中(例如添加了Python 3.4特有的东西),但是我会尽量将所有的东西组合在一起。

注意 :我要发布的每一个Python标准库代码都属于版本3.5.3 (doc引用是特定于版本3的 )。

问题陈述

  1. 检查文件( 可争论 :也是文件夹(“特殊”文件)?)的存在
  2. 不要使用try/except/else/finally

可能的scheme

  1. [Python]:os.path.exists (同样检查其他函数族成员,如os.path.isfileos.path.isdiros.path.lexists用于稍微不同的行为)

     os.path.exists(path) 

    如果path指向现有path或打开的文件描述符,则返回True 。 对于错误的符号链接返回False 。 在某些平台上,如果在所请求的文件上没有授予权限来执行os.stat() ,则该函数可能返回False ,即使path物理上存在。

    一切都很好,但是如果按照导入树:

    • os.pathposixpath.pyntpath.py

      • genericpath.py ,行〜#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 

    它只是围绕[Python]的一个try/except块:os.stat 。 所以,你的代码try/except免费的,但在框架中至less有一个这样的块。 这也适用于其他funcs( 包括 os.path.isfile )。

    1.1。 [Python]:pathlib.Path.is_file

    • 这是一个发烧友(和更多的python ic)处理path, 但是
    • 在引擎盖下,它完全一样的东西( pathlib.py ,行〜#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]:os.access,其行为接近os.path.exists (实际上更广泛,主要是因为第二个参数)

    • 用户权限可能会限制文档“可见性”,如文档所述:

      …testing调用用户是否具有指定的path访问权限。 模式应该是F_OK来testingpath的存在…

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

    就我个人而言,我更喜欢这个,因为在底层 ,它调用本地API (通过“$ {PYTHON_SRC_DIR} /Modules/posixmodule.c” ):

    • Ux : [man]:ACCESS(2) (!!!注意关于其使用可能引入的安全漏洞的提示!!!)
    • Win : [MSDN]:GetFileAttributes函数

    注意 :调用本机API也可以通过[Python]:ctypes – Python的外部函数库 ,但在大多数情况下,它更复杂。

    (特定于Win ):由于msvcr *vcruntime * )导出了一个[MSDN]:_access,_waccess函数族,下面是一个例子:

     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", os.F_OK) -1 

    备注

    • 虽然这不是一个好习惯,但我在调用中使用了os.F_OK ,但这只是为了清楚(值为0
    • 我正在使用_waccess以便相同的代码在Python3Python2上工作 (尽pipe它们之间有unicode相关的差异)
    • 虽然这是针对一个非常具体的领域, 但以前的任何答案都没有提到

    LnxUbtu(16 x64) )也是如此:

     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"/tmp1", os.F_OK) -1 

    备注

    • 相反,硬编码libc的path( “/lib/x86_64-linux-gnu/libc.so.6” )可能(而且很可能会)跨系统变化, None (或空string)可以传递给CDLL构造函数( ctypes.CDLL(None).access(b"/tmp", os.F_OK) )。 根据[男子]:DLOPEN(3) :

      如果filename是NULL,则返回的句柄是主程序。 当给予dlsym ()时,这个句柄将导致在主程序中search一个符号,然后在程序启动时加载所有的共享对象,然后使用dlopen ()加载的所有共享对象的标志为RTLD_GLOBAL

      • 主(当前)程序( python )与libc链接,所以它的符号(包括access )将被加载
      • 这个必须小心处理,因为像mainPy_Main和(所有)其他函数都是可用的; 称他们可能会有灾难性的影响(在目前的计划)
      • 这并不适用于Win (但这并不是什么大问题,因为msvcrt.dll位于%SystemRoot%\ System32中,默认情况下是%PATH% )。 我想进一步采取行动并在Win上复制这种行为(并提交补丁),但事实certificate, [MSDN]:GetProcAddress函数只能“看到” 导出的符号,所以除非有人将主函数声明为__declspec(dllexport) (为什么地球上的普通人会这样做?),主程序是可加载的,但几乎不可用
  3. 使用[Python]:使用语句上下文pipe理器 。 或者:

    • 创build一个:

       class Swallow: # Dummy example def __enter__(self): print("Entering...") def __exit__(self, exc_type, exc_value, exc_traceback): print("Exiting:", exc_type, exc_value, exc_traceback) return True 
      • 它的用法 – 我将复制isfile行为(注意,这只是为了演示的目的,不要试图编写这样的代码进行生产 ):

         import os import stat def isfile2(path): result = False with Swallow(): result = stat.S_ISREG(os.stat(path).st_mode) return result 
    • 使用[Python]:contextlib.suppress(* exceptions) – 这是专门为select性抑制exception而devise的

    但是,它们似乎是try/except/else/finally块的封装,如[Python]:with语句指出:

    这允许共同的尝试 … 除了 … 最终的使用模式被封装以方便重用。

  4. 使用文件系统遍历function(并search匹配项目的结果)

    • [Python]:os.listdir
      • 它下面使用[man]:opendir ( [MSDN]:FindFirstFile函数 )函数族
    • [Python]:os.walk
      • 它使用os.listdir (或在某些情况下os.scandir
    • [Python]:glob.iglob
      • 似乎并不是遍历函数(至less在某些情况下),但它仍然使用os.listdir

    由于这些文件迭代了文件夹,所以对于我们的问题来说效率不高,所以我不会坚持。 更不用说在某些情况下,可能需要文件名处理。

  5. 安装一些具有文件系统function的第三方模块

    最有可能的,将依靠上述方式之一(也许有轻微的自定义)。
    一个例子是(再次,特定于Win ) [SourceForge]:Python的Windows扩展(pywin32) ,这是一个Python包装WINAPI

    但是,因为这更像是一个解决方法( 增益 ),我在这里停下来。

另外, os.access()

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

R_OKW_OKX_OK是用于testing权限( doc )的标志。

在Python 3.4中,该语言提供了一个新的模块来pipe理文件:

 import pathlib path = pathlib.Path('path/to/file') if path.is_file(): # If you want to check a directory: path.is_dir() # If it is true, return true on your code. 

只是为了增加混淆,似乎以前build议的try:open()方法在Python中不起作用,因为文件访问不是排他性的,即使在写入文件时也是如此,比如什么是打开在Python中的独占访问文件? 。

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

在您的程序中,提升exception被认为是可接受的,Pythonic的stream程控制方法。 考虑用IOErrors处理丢失的文件。 在这种情况下,如果文件存在但用户没有读取权限,则会引发IOErrorexception。

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

下面是Linux命令行环境的一行Python命令。 我觉得这很好,因为我不是一个热门的Bash家伙。

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

我希望这是有帮助的。

你可以写下Brian的build议,不用try:

 from contextlib import suppress with suppress(IOError), open('filename'): process() 

suppress是Python 3.4的一部分。 在较旧的版本中,您可以快速编写自己的压制:

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

添加一个其他答案中没有完全反映的细微变化。

这将处理file_pathNone或空string的情况。

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

根据Shahbaz的build议添加变体

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

根据Peter Wood的build议添加变体

 def file_exists(file_path): return file_path and os.path.isfile(file_path): 

你可以使用Python的“OS”库:

 >>> import os >>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") True >>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx") False 

我是一个已经存在了大约10年的软件包的作者,它有一个直接解决这个问题的函数。 基本上,如果你在非Windows系统上,它使用Popen来访问find 。 但是,如果您使用的是Windows,则find使用高效的文件系统助手来复制find

代码本身不使用try块…除了在确定操作系统,因此指导你的“Unix”风格的find或手buillt find 。 时序testing表明,在确定操作系统的try更快,所以我在那里使用了一个(但没有其他地方)。

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

 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.

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

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) 

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

 open(inputFile, 'r')