如何毫无例外地检查一个文件是否存在?

2024-11-20 08:44:00
admin
原创
8
摘要:问题描述:如何在不使用语句的情况下检查文件是否存在try?解决方案 1:如果您检查的原因是为了执行类似 的操作if file_exists: open_it(),则在尝试打开文件时使用 会更安全try。检查然后打开文件可能会在检查和尝试打开文件之间被删除或移动或发生其他情况。如果您不打算立即打开该文件,您可以...

问题描述:

如何在不使用语句的情况下检查文件是否存在try


解决方案 1:

如果您检查的原因是为了执行类似 的操作if file_exists: open_it(),则在尝试打开文件时使用 会更安全try。检查然后打开文件可能会在检查和尝试打开文件之间被删除或移动或发生其他情况。

如果您不打算立即打开该文件,您可以使用os.path.isfile它来确保它是一个文件。

True如果路径是现有的常规文件,则返回。这将遵循符号链接,因此对于同一路径,islink()和isfile()都可以为真。

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

pathlib

从 Python 3.4 开始,该pathlib模块提供了一种面向对象的方法(在 Python 2.7 中反向移植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()

if my_file.exists():
    # path exists

您也可以resolve(strict=True)try块中使用:

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

解决方案 2:

用于os.path.exists检查文件和目录:

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

用于os.path.isfile仅检查文件(注意:跟随符号链接):

os.path.isfile(file_path)

解决方案 3:

与 不同isfile(),对于目录,exists()将返回True。因此,根据您是只想要纯文件还是目录,您将使用isfile()exists()。以下是一些简单的REPL输出:

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

解决方案 4:

import os

if os.path.isfile(filepath):
   print("File exists")

解决方案 5:

使用:os.path.isfile()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")

解决方案 6:

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

解决方案 7:

尽管现有答案(至少其中一个)中列出了几乎所有可能的方法(例如添加了Python 3.4特定内容),但我会尝试将所有内容组合在一起。

注意:我将要发布的每一段Python标准库代码都属于3.5.3版本。

问题陈述

  1. 检查文件(有争议:还有文件夹(“特殊”文件)?)的存在

  2. 不要使用try / except / else / finally

可能的解决方案

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

另外,检查其他函数家族成员如os.path.isfileos.path.isdiros.path.lexists是否有略微不同的行为:

True如果路径指向现有路径或打开的文件描述符,则返回。如果False符号链接损坏,则返回。在某些平台上,False如果未授予对请求的文件执行os.stat()的权限,即使路径实际存在,此函数也可能返回。

一切都很好,但如果遵循导入树:

  • os.path-posixpath.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.Docs]周围的try / except块: os.stat(path, , dir_fd=None, follow_symlinks=True) 。因此,您的代码是try / except免费的,但在帧堆栈的较低位置至少有一个这样的块。这也适用于其他函数(包括os.path.isfile*)。

1.1. [Python.Docs]: pathlib - Path.is_file()
  • 这是一种更奇特(也更[Wiktionary]: Pythonic)的处理路径的方式,但是

  • 在底层,它做了完全相同的事情(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]: 使用语句上下文管理器

任何一个:

  • 创建一个:

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
+ 它的用法——我将复制*os.path.isfile*行为(请注意,这只是为了演示目的,不要**尝试为***生产*编写这样的代码):


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
  • 使用[Python.Docs]: contextlib.suppress(*exceptions) -专门用于选择性抑制异常

但是,它们似乎是try / except / else / finally块的包装器,如[Python.Docs]:复合语句 - with 语句所述:

这允许封装常见的try ... except ... finally使用模式以便于重用。

3. 文件系统遍历函数

在结果中搜索匹配的项目:

* 在底层,两者都使用:


    + *Nix*:[Man7]: OPENDIR(3) / [Man7]: READDIR(3) / [Man7]: CLOSEDIR(3)
    + *Win*:[MS.Learn]:FindFirstFileW 函数(fileapi.h) / [MS.Learn]:FindNextFileW 函数(fileapi.h) / [MS.Learn]:FindClose 函数(fileapi.h)通过[GitHub]: python/cpython - (主要) cpython/Modules/posixmodule.c

使用scandir()代替listdir()可以显著提高需要文件类型或文件属性信息的代码的性能,因为如果操作系统在扫描目录时提供这些信息,os.DirEntry对象就会公开这些信息。所有os.DirEntry方法都可以执行系统调用,但is_dir()和is_file()通常只需要对符号链接进行系统调用;os.DirEntry.stat()在 Unix 上始终需要系统调用,但在 Windows 上只需要对符号链接进行系统调用。

* 使用*os.listdir* (可用时使用*os.scandir* )
* *本身*似乎不是一个遍历函数(至少在某些情况下),但它仍然使用*os.listdir*

由于这些遍历文件夹(在大多数情况下),它们对于我们的问题来说效率低下(也有例外,例如非通配符通配符 - 正如@ShadowRanger 指出的那样),所以我不会坚持使用它们。更不用说在某些情况下,可能需要文件名处理。

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

它的行为接近os.path.exists(实际上它更广泛,主要是因为第二个参数)。

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

...测试调用用户是否具有对路径的指定访问权限。模式应该是F_OK以测试路径的存在...

  • 安全注意事项

在使用open()实际执行操作之前,使用access()检查用户是否有权打开文件会产生安全漏洞,因为用户可能会利用检查和打开文件之间的短暂时间间隔来对其进行操作。

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

由于我也使用C 语言,因此我也使用此方法,因为在底层,它调用API(再次通过“ ${PYTHON_SRC_DIR}/Modules/posixmodule.c ”),但它也为可能的用户错误*打开了一扇大门,并且它不像其他变体那样具有Python* ic。因此,除非您知道自己在做什么,否则不要使用它:

  • Nix : [Man7]: 访问(2)

警告:使用这些调用来检查用户是否有权(例如,在使用open(2)实际打开文件之前)打开文件会造成安全漏洞,因为用户可能会利用检查和打开文件之间的短暂时间间隔来操作文件。因此,应避免使用此系统调用

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

正如所见,强烈不建议采用这种方法(尤其是在Nix上)。

注意:也可以通过[Python.Docs]: ctypes - A foreign function library for Python调用本机API,但在大多数情况下它更复杂。在使用CTypes之前,请检查[SO]: C function called from Python via ctypes returns invalid value (@CristiFati's answer)。

Win专用):由于vcruntime###.dll(旧版VStudio为msvcr###.dll - 我将其称为UCRT)也导出[MS.Learn]:_access、_waccess函数系列,因此这里有一个示例(请注意,推荐的[Python.Docs]:msvcrt - MS VC++ 运行时中的有用例程不会导出它们):

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

注意

  • 虽然这不是一个好的做法,但我在调用中使用了os.F_OK ,但这只是为了清楚起见(它的值是0

  • 我正在使用_waccess,以便相同的代码可以在Python 3Python 2上运行(尽管[Wikipedia]:它们之间存在 Unicode 相关差异 - [SO]: 将 utf-16 字符串传递给 Windows 函数(@CristiFati 的答案))

  • 虽然这针对的是特定的领域,但之前的任何答案都没有提到

Linux (Ubuntu( [维基百科]:Ubuntu版本历史)16 x86_64pc064))对应版本如下:

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

注意

  • 可以将None(或空字符串)传递给CDLL构造函数 ( ),而不是对libc.so ( LibC ) 的路径 (" /lib/x86_64-linux-gnu/libc.so.6 ") 进行硬编码,因为该路径可能(并且很可能)因系统而异。根据[Man7]: DLOPEN(3):ctypes.CDLL(None).access(b"/tmp", os.F_OK)

如果filename为 NULL,则返回的句柄用于主程序。当将此句柄提供给dlsym(3)时,它将搜索主程序中的符号,然后搜索程序启动时加载的所有共享对象,然后搜索由dlopen () 使用标志RTLD_GLOBAL加载的所有共享对象。

  • 主(当前)程序(python )与LibC链接,因此其符号(包括访问)将被加载

  • 这必须小心处理,因为mainPy_Main和(所有)其他函数都可用;调用它们可能会对(当前程序)造成灾难性的影响

  • 这不适用于Windows(但这不是什么大问题,因为UCRT位于“ %SystemRoot%\System32 ”,默认情况下位于%PATH%中)。我想进一步在Windows上复制此行为(并提交补丁),但事实证明,[MS.Learn]:GetProcAddress 函数(libloaderapi.h)仅“看到”导出的符号,因此除非有人在主可执行文件中声明这些函数__declspec(dllexport)(为什么普通人会这样做?),否则主程序是可加载的,但几乎无法使用

5.具有文件系统功能的第三方模块

最有可能的是,将依赖于上述方法之一(可能略有定制)。
一个例子是(同样,特定于Win)[GitHub]: mhammond/pywin32 - Python for Windows (pywin32) Extensions,它是WinAPI的Python包装器。

但是,因为这更像是一种解决方法,所以我就此打住。

6.系统管理员方法

我认为这是一个(蹩脚的)解决方法(gainarie):使用Python作为包装器来执行 shell 命令:

(py35x64_test) [cfati@CFATI-5510-0:e:WorkDevStackOverflowq000082831]> "e:WorkDevVEnvspy35x64_testScriptspython.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\Temp\" > nul 2>&1'))"
0

(py35x64_test) [cfati@CFATI-5510-0:e:WorkDevStackOverflowq000082831]> "e:WorkDevVEnvspy35x64_testScriptspython.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\Temp.notexist\" > nul 2>&1'))"
1
  • Nix([维基百科]:类 Unix) - 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

底线:

  • 使用try / except / else / finally块,因为它们可以防止你遇到一系列棘手的问题

  • 我能想到的一个可能的反例是性能:这样的块成本很高,因此尽量不要将它们放在每秒运行数十万次的代码中(但由于(在大多数情况下)它涉及磁盘访问,所以情况并非如此)

解决方案 8:

Python 3.4+有一个面向对象的路径模块: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 模块有很多很酷的东西:方便的通配符、检查文件所有者、更简单的路径连接等。值得一试。如果您使用的是较旧的 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

解决方案 9:

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

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

解决方案 10:

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

从 Python 3.4 开始可用,导入并实例化Path具有文件名的对象,并检查is_file方法(请注意,对于指向常规文件的符号链接,这也返回 True):

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

如果你使用的是 Python 2,则可以从 pypi 反向移植 pathlib 模块,pathlib2或者isfileos.path模块中进行检查:

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

现在,以上内容可能是这里最好的务实直接答案,但是存在竞争条件的可能性(取决于您要完成的任务),并且底层实现使用了try,但 Pythontry在其实现中到处都使用。

因为 Pythontry到处使用,所以实际上没有理由避免使用它的实现。

但这个答案的其余部分试图考虑这些警告。

更长、更迂腐的答案

Path从 Python 3.4 开始可用,使用中的新对象pathlib。请注意,这.exists并不完全正确,因为目录不是文件(除了在 unix 意义上一切都是文件)。

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

所以我们需要使用is_file

>>> root.is_file()
False

以下是 的帮助is_file

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

因此让我们获取一个我们知道是文件的文件:

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

默认情况下,NamedTemporaryFile关闭时会删除文件(当不再有对它的引用时将自动关闭)。

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

竞争条件:为什么我们喜欢尝试

我们喜欢try它,因为它避免了竞争条件。使用try,您只需尝试读取文件,期望它在那里,如果没有,您就会捕获异常并执行任何合理的后备行为。

如果您想在尝试读取文件之前检查它是否存在,并且您可能会删除它,然后您可能会使用多个线程或进程,或者另一个程序知道该文件并可能删除它 - 如果您检查它是否存在,则可能会有竞争条件的风险,因为您会在其条件(其存在)改变之前争相打开它。

竞争条件很难调试,因为它们很可能在很短的时间内导致程序失败。

但如果这是您的动机,您可以try使用上下文管理器获取语句的值suppress

不使用 try 语句来避免竞争条件:suppress

Python 3.4 为我们提供了suppress上下文管理器(以前称为ignore上下文管理器),它在语义上用更少的行完成完全相同的事情,同时(至少从表面上看)满足了最初避免try声明的要求:

from contextlib import suppress
from pathlib import Path

用法:

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

对于早期的 Python,您可以自行编写suppress,但不使用try会比使用更冗长。我确实相信这实际上是唯一一个try在 Python 3.4 之前的任何级别都未使用的答案,因为它使用了上下文管理器:

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

其他不符合“无需尝试”要求的选项:

伊斯菲勒

import os
os.path.isfile(path)

来自文档:

os.path.isfile(path)

如果路径是现有的常规文件,则返回 True。这将遵循符号链接,因此对于同一路径islink(),和可以同时为真。isfile()

但是如果你检查这个函数的源代码,你会发现它实际上使用了 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

它所做的就是使用给定的路径来查看是否可以获取其统计信息,OSError然后捕获它,如果没有引发异常则检查它是否是一个文件。

如果您打算对该文件执行某些操作,我建议直接尝试使用 try-except 以避免竞争条件:

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

操作系统访问

适用于 Unix 和 Windows 的是os.access,但要使用,您必须传递标志,并且它不区分文件和目录。这更多用于测试实际调用用户是否在提升权限的环境中具有访问权限:

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

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

注意:在使用 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.access。它是一种低级函数,与上面讨论的高级对象和函数相比,更容易出现用户错误。

对另一个答案的批评:

另一个答案是这样说的os.access

就我个人而言,我更喜欢这个,因为在底层,它调用本机 API(通过“${PYTHON_SRC_DIR}/Modules/posixmodule.c”),但它也为可能的用户错误打开了大门,并且它不像其他变体那样 Pythonic:

这个答案说它更喜欢非 Pythonic、容易出错的方法,没有任何理由。它似乎鼓励用户在不理解底层 API 的情况下使用它们。

它还创建了一个上下文管理器,通过无条件返回True,允许所有异常(包括KeyboardInterruptSystemExit!)静默传递,这是隐藏错误的好方法。

这似乎鼓励用户采取不良的做法。

解决方案 11:

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

不要相信我的话。有很多证据支持这一理论。以下是一些证据:

  • 样式:软件设计课程笔记的“处理异常情况”部分(2007 年)

  • 避免竞争条件

解决方案 12:

使用:

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

导入os使您能够更轻松地使用操作系统导航和执行标准操作。

作为参考,另请参阅如何检查文件是否存在而没有异常?

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

解决方案 13:

使用 和 测试文件和os.path.isfile()文件os.path.isdir()os.path.exists()

假设“路径”是有效路径,下表显示每个函数针对文件和文件夹返回的内容:

在此处输入图片描述

您还可以通过获取扩展名来测试文件是否属于某种类型的文件os.path.splitext()(如果您还不知道的话)

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

解决方案 14:

TL;DR

答案是:使用pathlib模块


Pathlib可能是几乎所有文件操作最现代、最方便的方法。对于文件文件夹是否存在,一行代码就足够了。如果文件不存在,它不会抛出任何异常。

from pathlib import Path

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

pathlib模块是在 Python 3.4 中引入的,因此您需要使用 Python 3.4+。这个库使您在处理文件和文件夹时更加轻松,而且使用起来非常方便。以下是有关它的更多文档:pathlib — 面向对象的文件系统路径

顺便说一句,如果您要重复使用该路径,那么最好将其分配给变量。

因此它将变成:

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.

解决方案 15:

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

解决方案 16:

try/except 和 之间似乎没有有意义的功能差异isfile(),因此您应该使用有意义的那个。

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

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'

如果您需要文件锁定,那就是另一回事了。

解决方案 17:

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

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

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

解决方案 18:

日期:2017-12-04

其他答案中已列出所有可能的解决方案。

检查文件是否存在的直观且有争议的方法如下:

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

我制作了一个详尽的备忘单供您参考:

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

解决方案 19:

尽管我总是建议使用tryexcept语句,但这里也为您提供了几种可能性(我个人最喜欢使用os.access):

  1. 尝试打开文件:

打开文件将始终验证文件是否存在。您可以像这样创建一个函数:

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

如果为 False,则在 Python 的更高版本中,它将以未处理的 IOError 或 OSError 停止执行。要捕获异常,您必须使用 try except 子句。当然,您始终可以使用tryexcept` 语句,如下所示(感谢hsandt
让我思考):

def File_Existence(filepath):
    try:
        f = open(filepath)
    except IOError, OSError: # Note OSError is for later versions of Python
        return False

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

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

无论如何,这里:

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

我还应该提到,有两种方法无法验证文件是否存在。问题可能是permission deniedno such file or directory。如果您发现IOError,请设置IOError as e(如我的第一个选项),然后输入,print(e.args)这样您就可以确定您的问题。希望这对您有所帮助!:)

解决方案 20:

如果文件需要打开,您可以使用以下技术之一:

with open('somefile', 'xt') as f: # Using the x-flag, Python 3.3 and above
    f.write('Hello
')

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

注意:这将查找具有给定名称的文件或目录。

解决方案 21:

此外,os.access()

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

存在R_OK、、W_OK以及X_OK用于测试权限的标志(doc)。

解决方案 22:

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

引发异常被认为是程序中流程控制的一种可接受且符合 Python 风格的处理方法。考虑使用 IOError 处理丢失的文件。在这种情况下,如果文件存在但用户没有读取权限,则会引发 IOError 异常。

来源:使用 Python:如何检查文件是否存在

解决方案 23:

检查文件或目录是否存在

您可以按照以下三种方式操作:

1. 使用 isfile()

注 1:os.path.isfile仅用于文件

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

2. 使用exists

注 2:os.path.exists用于文件和目录

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

3.pathlib.Path方法(包含在Python 3+中,可使用pip为Python 2安装)

from pathlib import Path
Path(filename).exists()

解决方案 24:

如果您已经出于其他目的导入了 NumPy,则无需导入其他库pathlib,如os、、paths等。

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

根据其存在性,它将返回真或假。

解决方案 25:

您可以写 Brian 的建议而不使用try:

from contextlib import suppress

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

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

from contextlib import contextmanager

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

解决方案 26:

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

代码本身不使用try块……除非确定操作系统,从而引导您使用“Unix”风格find或手工构建的find。时间测试表明try确定操作系统的速度更快,所以我在那里使用了一个(但在其他地方没有使用)。

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

还有文档……

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

>>>

如果您想了解实现方法,请参见此处:
https ://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190

解决方案 27:

这是 Linux 命令行环境中的一行 Python 命令。我发现这非常方便,因为我不太擅长使用 Bash。

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

解决方案 28:

添加一个在其他答案中并未准确反映的细微变化。

file_path这将处理存在或空字符串的情况None

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

根据 Shahbaz 的建议添加变体

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

根据 Peter Wood 的建议添加变体

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

解决方案 29:

如何在不使用 try 语句的情况下检查文件是否存在?

在 2016 年,这仍然可以说是检查文件是否存在以及它是否是文件的最简单的方法:

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

isfile实际上只是一个辅助方法,内部使用os.statstat.S_ISREG(mode)位于其下。这os.stat是一个较低级别的方法,它将为您提供有关文件、目录、套接字、缓冲区等的详细信息。有关 os.stat 的更多信息,请点击此处

注意:但是,这种方法不会以任何方式锁定文件,因此您的代码可能容易受到“检查时间到使用时间”(TOCTTOU)错误的影响。

因此,引发异常被认为是程序中流程控制的一种可接受且符合 Python 规范的方法。并且应该考虑使用 IOError 而不是if语句来处理丢失的文件(这只是一个建议)。

解决方案 30:

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

>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用