如何在不使用 try
语句的情况下检查文件是否存在?
my_path.exists()
。
my_path.exists()
是不够的。 my_path.is_file()
会告诉您它是否是一个文件(可能适合阅读)。但是如果你想创建文件,你还必须检查 exists
以便排除文件系统中会导致失败的目录或其他非文件内容。
如果您检查的原因是您可以执行 if file_exists: open_it()
之类的操作,那么在尝试打开它时使用 try
会更安全。检查然后打开可能会导致文件被删除或移动,或者在检查和尝试打开文件之间存在风险。
如果您不打算立即打开文件,可以使用 os.path.isfile
如果 path 是现有的常规文件,则返回 True。这遵循符号链接,因此 islink() 和 isfile() 对于同一路径都可以为真。
import os.path
os.path.isfile(fname)
如果您需要确定它是一个文件。
从 Python 3.4 开始,pathlib
module 提供了一种面向对象的方法(在 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
您还可以在 try
块中使用 resolve(strict=True)
:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
使用 os.path.exists
检查文件和目录:
import os.path
os.path.exists(file_path)
使用 os.path.isfile
仅检查文件(注意:遵循符号链接):
os.path.isfile(file_path)
与 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
import os
if os.path.isfile(filepath):
print("File exists")
将 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")
os.access()
将返回 false。
import os
,您不需要再次import os.path
,因为它已经是 os
的一部分。如果您只想使用来自 os.path
而不是来自 os
本身的函数,则只需要导入 os.path
来导入较小的东西,但是当您使用 os.access
和 os.R_OK
时,第二个导入是没有必要。
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
尽管几乎所有可能的方式都列在(至少一个)现有答案中(例如添加了 Python 3.4 特定的东西),但我会尝试将所有内容组合在一起。
注意:我要发布的每一段 Python 标准库代码都属于 3.5.3 版本。
问题陈述:
检查文件(有争议:还有文件夹(“特殊”文件)?)存在不要使用try / except / else / finally块
可能的解决方案:
[Python 3]: os.path.exists(path) (还检查其他函数系列成员,如 os.path.isfile、os.path.isdir、os.path.lexists 的行为略有不同) os.path.exists(path ) 如果 path 引用现有路径或打开的文件描述符,则返回 True。对于损坏的符号链接返回 False。在某些平台上,如果未授予对请求的文件执行 os.stat() 的权限,即使路径物理存在,此函数也可能返回 False。一切都很好,但是如果遵循导入树: os.path - posixpath.py (ntpath.py) genericpath.py, line ~#20+ def exists(path): """测试路径是否存在。如果损坏则返回 False符号链接""" try: st = os.stat(path) except os.error: return False return True 这只是一个 try / except [Python 3] 周围的块: os.stat(path, *, dir_fd=None, follow_symlinks =真)。因此,您的代码是 try / except free,但在框架堆栈的较低位置(至少)有一个这样的块。这也适用于其他函数(包括 os.path.isfile)。 1.1。 [Python 3]:Path.is_file() 这是一种处理路径的更高级(和更 Pythonic)的方式,但在底层,它做的事情完全相同(pathlib.py,行 ~#1330):def is_file(self) : """ 此路径是否为常规文件(对于指向常规文件的符号链接也为 True)。 """ try: return S_ISREG(self.stat().st_mode) except OSError as e: if e.errno not in ( ENOENT, ENOTDIR): raise # Path 不存在或者是一个损坏的符号链接 # (参见 https://bitbucket.org/pitrou/pathlib/issue/12/) return False [Python 3]: With Statement Context Managers。任一: 创建一个: class Swallow: # Dummy examplespokened_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 # 只吞下 FileNotFoundError (不是例如 TypeError - 如果用户传递了错误的参数,如 None 或 float 或...)及其用法 - 我将复制 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 3]: contextlib.suppress(*exceptions) - 专为选择性抑制异常而设计 但是,它们似乎是 try / except / else / finally 块的包装器,如 [Python 3]:with 语句指出:这允许常见的 try...except...finall y 使用模式被封装以方便重用。文件系统遍历函数(并搜索匹配项的结果)[Python 3]:os.listdir(path='.')(或 [Python 3]:os.scandir(path='.') 在 Python v3 上.5+, backport: [PyPI]: scandir) 在底层,两者都使用:Nix: [man7]: OPENDIR(3) / [man7]: READDIR(3) / [man7]: CLOSEDIR(3) Win: [ MS.Docs]:FindFirstFileW 函数/[MS.Docs]:FindNextFileW 函数/[MS.Docs]:FindClose 函数通过 [GitHub]:python/cpython - (master) cpython/Modules/posixmodule.c 使用 scandir() 代替listdir() 可以显着提高还需要文件类型或文件属性信息的代码的性能,因为如果操作系统在扫描目录时提供了这些信息,os.DirEntry 对象就会公开这些信息。所有 os.DirEntry 方法都可以执行系统调用,但 is_dir() 和 is_file() 通常只需要对符号链接进行系统调用; os.DirEntry.stat() 在 Unix 上总是需要一个系统调用,但在 Windows 上只需要一个用于符号链接。 [Python 3]: os.walk(top, topdown=True, onerror=None, followlinks=False) 它使用 os.listdir (os.scandir 如果可用) [Python 3]: glob.iglob(pathname, *, recursive= False)(或其前身:glob.glob)本身似乎不是一个遍历函数(至少在某些情况下),但它仍然使用 os.listdir 由于这些迭代文件夹,(在大多数情况下)它们是对于我们的问题效率低下(有例外,如非通配符通配符 - 正如@ShadowRanger 指出的那样),所以我不会坚持使用它们。更不用说在某些情况下,可能需要文件名处理。 [Python 3]: os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True) 其行为接近 os.path.exists (实际上它更广泛,主要是因为第二个参数)用户如文档所述,权限可能会限制文件“可见性”: ...测试调用用户是否具有对路径的指定访问权限。模式应该是 F_OK 来测试路径的存在... os.access("/tmp", os.F_OK) 因为我也在 C 中工作,所以我也使用这个方法,因为在引擎盖下,它调用本机 API(再次,通过“${PYTHON_SRC_DIR}/Modules/posixmodule.c”),但它也为可能的用户错误打开了大门,而且它不像其他变体那样 Pythonic。因此,正如@AaronHall 正确指出的那样,除非您知道自己在做什么,否则不要使用它: Nix: [man7]: ACCESS(2) (!!!注意有关其使用可能引入的安全漏洞的说明!!!) Win: [MS.Docs]: GetFileAttributesW function 注意:调用本机 API 也可以通过 [Python 3]:ctypes - Python 的外部函数库,但在大多数情况下它更复杂。 (特定于 Win):由于 vcruntime* (msvcr*) .dll 还导出了 [MS.Docs]: _access, _waccess 函数系列,因此这里有一个示例:Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16 :02:32) [MSC v.1900 64 位 (AMD64)] 在 win32 上键入“帮助”、“版权”、“信用”或“许可证”以获取更多信息。 >>> 导入操作系统,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 注意:虽然这不是一个好习惯,但我在调用,但这只是为了清楚起见(它的值为 0)我使用 _waccess 以便相同的代码适用于 Python3 和 Python2(尽管它们之间存在 unicode 相关的差异)虽然这针对一个非常具体的领域,但没有提到在之前的任何答案中 Lnx (Ubtu (16 x64)) 对应物:Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux 输入“帮助”, “版权”、“学分”或“许可”以获取更多信息。 >>> 导入操作系统,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 注意:改为硬编码libc的路径("/lib/x86_64-linux -gnu/libc.so.6") 可能(并且很可能会)因系统而异,无(或空字符串)可以传递给 CDLL 构造函数 (ctypes.CDLL(None).access(b"/tmp ", os.F_OK))。根据 [man7]: DLOPEN(3): If filename is NULL, 那么返回的句柄是主程序的。当给 dlsym() 时,这个句柄会导致在主程序中搜索一个符号,然后是程序启动时加载的所有共享对象,然后是 dlopen() 加载的所有共享对象,带有标志 RTLD_GLOBAL。主(当前)程序(python)与 libc 链接,因此将加载其符号(包括访问权限) 这必须小心处理,因为 main、Py_Main 和(所有)其他函数都可用;调用它们可能会产生灾难性影响(对当前程序) 这也不适用于 Win(但这并不是什么大不了的事,因为 msvcrt.dll 位于“%SystemRoot%\System32”中,它位于 %PATH% by默认)。我想更进一步并在 Win 上复制此行为(并提交补丁),但事实证明,[MS.Docs]:GetProcAddress 函数仅“看到”导出的符号,因此除非有人在主可执行文件中声明这些函数作为 __declspec(dllexport) (为什么地球上的普通人会这样做?),主程序是可加载的,但几乎无法使用安装一些具有文件系统功能的第三方模块很可能会依赖上述方法之一(也许与轻微的定制)。一个示例是(同样,特定于 Win)[GitHub]:mhammond/pywin32 - Python for Windows (pywin32) Extensions,它是 WINAPI 上的 Python 包装器。但是,由于这更像是一种解决方法,所以我在这里停下来。另一个(蹩脚的)解决方法(gainarie)是(我喜欢这样称呼它)系统管理员方法:使用 Python 作为包装器来执行 shell 命令 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 "导入操作系统;打印(os.system('ls \"/tmp.notexist\" > /dev/null 2>&1'))" 512
底线:
一定要使用 try / except / else / finally 块,因为它们可以防止你遇到一系列讨厌的问题。我能想到的一个反例是性能:这样的块很昂贵,所以尽量不要将它们放在应该每秒运行数十万次的代码中(但因为(在大多数情况下)它涉及磁盘访问,不会是这样)。
最后说明:
我会尽量保持最新,欢迎任何建议,我会将任何有用的东西纳入答案
glob.iglob
(and glob.glob
as well) are based on os.scandir
,所以现在很懒;要在 10M 个文件的目录中获得第一次点击,您只需扫描直到第一次点击。即使在 3.6 之前,如果您使用不带任何通配符的 glob
方法,该函数也很智能:它知道您只能命中一次,因此 it simplifies the globbing to just os.path.isdir
or os.path.lexists
(取决于路径是否以 /
结尾)。
os.path.isdir
或 os.path.lexist
慢,因为它是一堆Python 级别的函数调用和字符串操作在它决定有效路径可行之前,但没有额外的系统调用或 I/O 工作,这要慢几个数量级)。
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
pathlib.Path.exists
,它涵盖的情况比 is_file
多
这是检查文件是否存在的最简单方法。仅仅因为您检查时该文件存在并不能保证在您需要打开它时它会在那里。
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")
如何在不使用 try 语句的情况下使用 Python 检查文件是否存在?
现在从 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、pathlib2
反向移植 pathlib 模块,或者从 os.path
模块检查 isfile
:
>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False
现在上面可能是这里最好的实用直接答案,但是可能存在竞争条件(取决于您要完成的工作),并且底层实现使用 try
,但 Python 使用 {1 } 在其实现中无处不在。
因为 Python 在任何地方都使用 try
,所以没有理由避免使用它的实现。
但是这个答案的其余部分试图考虑这些警告。
更长,更迂腐的答案
从 Python 3.4 开始可用,使用 pathlib
中的新 Path
对象。请注意,.exists
并不完全正确,因为目录不是文件(除了 unix 意义上的 everything 是文件)。
>>> 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
但是,如果您深入研究 the implementation,您会发现 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
,您只需尝试读取您的文件,并期望它在那里,如果没有,您捕获异常并执行任何有意义的后备行为。
如果您想在尝试读取文件之前检查文件是否存在,并且您可能正在删除它,然后您可能正在使用多个线程或进程,或者另一个程序知道该文件并可以删除它 - 您可能会冒如果您检查它是否存在,则为竞争条件,因为您随后会在其条件(其存在)更改之前竞相打开它。
竞态条件很难调试,因为有一个非常小的窗口可能会导致程序失败。
但如果这是您的动机,您可以通过使用 suppress
上下文管理器获取 try
语句的值。
在没有 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 之前的任何级别均不使用 try
的唯一答案,因为它使用上下文管理器代替:
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)
来自 docs:
os.path.isfile(path) 如果 path 是现有的常规文件,则返回 True。这遵循符号链接,因此 islink() 和 isfile() 对于同一路径都可以为真。
但是,如果您检查此函数的 source,您会发现它确实使用了 try 语句:
这遵循符号链接,因此 islink() 和 isdir() 都可以为真 # 对于支持符号链接的系统上的相同路径 def isfile(path): """测试路径是否为常规文件""" 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
相同的竞争条件问题。从 docs:
注意:使用 access() 来检查用户是否被授权例如在使用 open() 实际打开文件之前打开文件会产生安全漏洞,因为用户可能会利用检查和打开文件之间的短时间间隔来操作它。最好使用 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" # 不是权限错误。引发 else: with fp: return fp.read()
避免使用 os.access
。它是一个低级函数,比上面讨论的高级对象和函数有更多的用户错误机会。
对另一个答案的批评:
另一个答案是关于 os.access
的:
就个人而言,我更喜欢这个,因为在底层,它调用原生 API(通过“${PYTHON_SRC_DIR}/Modules/posixmodule.c”),但它也为可能的用户错误打开了大门,而且它不像其他变体那样 Pythonic :
这个答案说它更喜欢非 Pythonic、容易出错的方法,没有任何理由。它似乎鼓励用户在不了解它们的情况下使用低级 API。
它还创建了一个上下文管理器,通过无条件返回 True
,允许所有异常(包括 KeyboardInterrupt
和 SystemExit
!)静默通过,这是隐藏错误的好方法。
这似乎鼓励用户采用不良做法。
更喜欢 try 语句。它被认为是更好的风格并避免了竞争条件。
不要相信我的话。这个理论有很多支持。这是一对:
样式:http://allendowney.com/sd/notes/notes11.txt 的“处理异常情况”部分
避免竞争条件
try...except
无助于解决 那个 问题。
except:
子句中会使您的这部分代码中出现的异常会引发令人困惑的消息(第二在第一个处理过程中出现错误。)
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!"
导入 os
可以更轻松地使用您的操作系统进行导航和执行标准操作。
如需参考,另请参阅 How to check whether a file exists using Python?
如果您需要高级操作,请使用 shutil
。
os.path.exists
对于不是文件的事物(例如目录)返回 true。这会产生误报。请参阅推荐 os.path.isfile
的其他答案。
使用 os.path.isfile()
、os.path.isdir()
和 os.path.exists()
测试文件和文件夹
假设“路径”是有效路径,下表显示了每个函数为文件和文件夹返回的内容:
https://i.stack.imgur.com/tOs9p.png
您还可以使用 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
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+,这个库使您在处理文件和文件夹时的生活更加轻松,而且它很好用,这里有更多关于它的文档({1 })。
顺便说一句,如果您要重用路径,那么最好将其分配给变量
所以会变成
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.
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():
...
pathlib
是 python 的路径 OOP 解决方案。你可以用它做更多的事情。如果你只需要检查存在,优势就没有那么大了。
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'
如果您需要文件锁定,那就另当别论了。
os.path.exists
对于不是文件的事物(例如目录)返回 true。这会产生误报。请参阅推荐 os.path.isfile
的其他答案。
filepath
的链接,并且 BAM,您将覆盖目标文件。您应该在 try...except
块中执行 open(filepath, 'wx')
以避免该问题。
filepath + '.old'
已经存在,您将得到一个 OSError
:“在 Windows 上,如果 dst 已经存在,即使它是一个文件也会引发 OSError;可能无法当 dst 命名现有文件时实现原子重命名。”
os.replace
可移植地执行目标文件的静默替换(它与 os.rename
的 Linux 行为相同)(仅当目标名称存在并且是目录时才会出错)。所以你被困在 2.x 上,但 Py3 用户几年来一直是一个不错的选择。
rename
示例中:仍应使用 try
/except
完成。 os.rename
(或现代 Python 上的 os.replace
)是原子的;使其检查然后重命名会引入不必要的竞争和额外的系统调用。做try: os.replace(filepath, filepath + '.old') except OSError: pass
你可以试试这个(更安全):
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')
然后,根据结果,您的程序可以从那里继续运行,或者您可以根据需要编写代码来停止它。
try
的解决方案
日期:2017-12-04
每个可能的解决方案都已在其他答案中列出。
检查文件是否存在的一种直观且有争议的方法如下:
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')
我制作了一份详尽的备忘单供您参考:
#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']}
虽然我总是建议使用 try
和 except
语句,但这里有一些可能性供您使用(我个人最喜欢使用 os.access
):
尝试打开文件:打开文件将始终验证文件是否存在。你可以像这样创建一个函数: def File_Existence(filepath): f = open(filepath) return True 如果它是 False,它将在更高版本的 Python 中以未处理的 IOError 或 OSError 停止执行。要捕获异常,您必须使用 try except 子句。当然,你总是可以像这样使用 try except` 语句(感谢 hsandt 让我思考): def File_Existence(filepath): try: f = open(filepath) except IOError, OSError: # Note OSError is for later versions Python 返回 False 返回 True 使用 os.path.exists(path):这将检查您指定的内容是否存在。但是,它会检查文件和目录,因此请注意您如何使用它。导入 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 使用 os.access(path, mode):这将检查您是否有权访问该文件。它将检查权限。根据 os.py 文档,输入 os.F_OK,它会检查路径是否存在。但是,使用它会造成安全漏洞,因为有人可以使用检查权限和打开文件之间的时间来攻击您的文件。您应该直接打开文件而不是检查其权限。 (EAFP 与 LBYP)。如果您以后不打算打开文件,只检查它的存在,那么您可以使用它。无论如何,在这里: >>> import os >>> os.access("/is/a/file.txt", os.F_OK) True
我还应该提到,有两种方法无法验证文件是否存在。问题将是 permission denied
或 no such file or directory
。如果您发现 IOError
,请设置 IOError as e
(就像我的第一个选项一样),然后输入 print(e.args)
,这样您就可以确定您的问题。我希望它有帮助! :)
如果文件用于打开,您可以使用以下技术之一:
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!')
更新
只是为了避免混淆,根据我得到的答案,当前答案会找到具有给定名称的文件或目录。
os.path.exists
对于不是文件的事物(例如目录)返回 true。这会产生误报。请参阅推荐 os.path.isfile
的其他答案。
此外,os.access()
:
if os.access("myfile", os.R_OK):
with open("myfile") as fp:
return fp.read()
作为 R_OK
、W_OK
和 X_OK
测试权限的标志 (doc)。
if os.path.isfile(path_to_file):
try:
open(path_to_file)
pass
except IOError as e:
print "Unable to open file"
引发异常被认为是一种可接受的 Pythonic 方法,用于在您的程序中进行流控制。考虑使用 IOErrors 处理丢失的文件。在这种情况下,如果文件存在但用户没有读取权限,则会引发 IOError 异常。
SRC:http://www.pfinn.net/python-check-if-file-exists.html
如果您已经出于其他目的导入了 NumPy,则无需导入其他库,如 pathlib
、os
、paths
等。
import numpy as np
np.DataSource().exists("path/to/your/file")
这将根据其存在返回 true 或 false。
您可以在没有 try:
的情况下编写 Brian 的建议。
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
检查文件或目录是否存在
您可以遵循以下三种方式:
Note1: os.path.isfile 仅用于文件
import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists
Note2: os.path.exists 用于文件和目录
import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists
pathlib.Path 方法(包含在 Python 3+ 中,可通过 Python 2 的 pip 安装)
from pathlib import Path
Path(filename).exists()
添加一个未完全反映在其他答案中的细微变化。
这将处理 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):
if (x) return true; else return false;
实际上只是 return x
。您的最后四行可以变成 return os.path.isfile(file_path)
。当我们这样做时,整个函数可以简化为 return file_path and os.path.isfile(file_path)
。
if (x)
,您必须小心使用 return x
。 Python 将考虑一个空字符串 False 在这种情况下我们将返回一个空字符串而不是一个布尔值。此函数的目的是始终返回 bool。
x
是 os.path.isfile(..)
,所以它已经是布尔值。
os.path.isfile(None)
引发异常,这就是我添加 if 检查的原因。我可能只是将它包装在 try/except 中,但我觉得这种方式更明确。
return file_path and os.path.isfile(file_path)
我是一个已经存在了大约 10 年的包的作者,它具有直接解决这个问题的功能。基本上,如果您在非 Windows 系统上,它使用 Popen
访问 find
。但是,如果您在 Windows 上,它会使用高效的文件系统遍历器复制 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
这是用于 Linux 命令行环境的 1 行 Python 命令。我觉得这很方便,因为我不是那么热的 Bash 人。
python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"
我希望这是有帮助的。
[ -f "${file}" ] && echo "file found" || echo "file not found"
(与 if [ ... ]; then ...; else ...; fi
相同)。
您可以使用 Python 的“OS”库:
>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt")
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
os.path.exists
对于不是文件的事物(例如目录)返回 true。这会产生误报。请参阅推荐 os.path.isfile
的其他答案。
exists
就可以了。如果目标是确定打开可能存在的文件是否安全,那么批评是有道理的并且存在不够精确。可悲的是,OP 没有指定哪个是期望的目标(并且可能不会再这样做了)。
如何在不使用 try 语句的情况下检查文件是否存在?
在 2016 年,这仍然可以说是检查文件是否存在以及它是否是文件的最简单方法:
import os
os.path.isfile('./file.txt') # Returns True if exists, else False
isfile
实际上只是一个在内部使用 os.stat
和 stat.S_ISREG(mode)
的辅助方法。此 os.stat
是一种较低级别的方法,它将为您提供有关文件、目录、套接字、缓冲区等的详细信息。 More about os.stat here
注意:但是,这种方法不会以任何方式锁定文件,因此您的代码可能容易受到“检查时间到使用时间”(TOCTTOU)错误的影响。
因此,引发异常被认为是一种可接受的 Pythonic 方法,用于在您的程序中进行流控制。并且应该考虑使用 IOErrors 而不是 if
语句来处理丢失的文件(只是一个建议)。
FileNotFoundError
是在 Python 3 中引入的。如果您还需要支持 Python 2.7 和 Python 3,则可以改用IOError
(它是FileNotFoundError
的子类)stackoverflow.com/a/21368457/1960959open('file', 'r+')
),然后搜索到最后。pathlib2
<pathlib
?pathlib
是针对 python3 的,对吧?我一直在使用pathlib2
,认为它更胜一筹。'a'
的情况下相互覆盖。