提问人:spence91 提问时间:9/17/2008 最后编辑:syntagmaspence91 更新时间:12/22/2022 访问量:5329250
如何检查文件是否存在,没有异常?
How do I check whether a file exists without exceptions?
答:
import os
if os.path.isfile(filepath):
print("File exists")
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
评论
使用 os.path.exists
检查文件和目录:
import os.path
os.path.exists(file_path)
使用 os.path.isfile
仅检查文件(注意:遵循符号链接):
os.path.isfile(file_path)
如果您要检查的原因是您可以执行类似 之类的操作,则使用周围尝试打开它更安全。检查然后打开文件可能会被删除或移动,或者在检查和尝试打开文件之间发生某些风险。if file_exists: open_it()
try
如果您不打算立即打开该文件,可以使用 os.path.isfile
如果 path 是现有的常规文件,则返回。这遵循符号链接,因此对于同一路径,islink() 和 isfile() 都可以为 true。
True
import os.path
os.path.isfile(fname)
如果您需要确定它是一个文件。
从 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
评论
FileNotFoundError
IOError
FileNotFoundError
open('file', 'r+')
pathlib2
pathlib
pathlib
pathlib2
'a'
此外:os.access()
if os.access("myfile", os.R_OK):
with open("myfile") as fp:
return fp.read()
是 、 和用于测试权限的标志 (doc)。R_OK
W_OK
X_OK
与 isfile(
) 不同,exists()
将返回目录。因此,根据您是只想要普通文件还是目录,您将使用 或 .以下是一些简单的 REPL 输出:True
isfile()
exists()
>>> 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
首选 try 语句。它被认为是更好的风格,并避免了比赛条件。
不要相信我的话。这个理论有很多支持。这是一对夫妇:
评论
try...except
except:
你可以试试这个(更安全):
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] 没有这样的文件或目录: '随便.txt')
然后,根据结果,您的程序可以从那里继续运行,或者您可以根据需要编写代码来停止它。
评论
try
import os
path = /path/to/dir
root,dirs,files = os.walk(path).next()
if myfile in files:
print "yes it exists"
这在检查多个文件时很有帮助。或者您想对现有列表进行设置交集/减法。
评论
os.walk
./FILE
./some/sub/folder/FILE
os.path.isfile()
将 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()
import os
import os.path
os
os.path
os.path
os
os.access
os.R_OK
这是检查文件是否存在的最简单方法。仅仅因为您检查时文件存在并不能保证当您需要打开它时它会在那里。
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/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
os.path.isfile
filepath
open(filepath, 'wx')
try...except
OSError
filepath + '.old'
os.replace
可移植地执行目标文件的静默替换(它与 Linux 行为相同)(仅当目标名称存在并且是目录时才会出错)。所以你被困在 2.x 上,但 Py3 用户已经有好几年了。os.rename
rename
try
except
os.rename
os.replace
try: os.replace(filepath, filepath + '.old') except OSError: pass
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
评论
你可以写 Brian 的建议,而不用 .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
您可以使用以下 open 方法来检查文件是否存在 + 可读:
file = open(inputFile, 'r')
file.close()
评论
如果文件用于打开,则可以使用以下方法之一:
with open('somefile', 'xt') as f: # Using the x-flag, Python 3.3 and above
f.write('Hello\n')
if not os.path.exists('somefile'):
with open('somefile', 'wt') as f:
f.write("Hello\n")
else:
print('File already exists!')
注意:这将查找具有给定名称的文件或目录。
评论
os.path.exists
os.path.isfile
要检查文件是否存在,
from sys import argv
from os.path import exists
script, filename = argv
target = open(filename)
print "file exists: %r" % exists(filename)
评论
您可以使用 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
os.path.isfile
exists
虽然我总是推荐使用 和 语句,但这里有一些可能性供您使用(我个人最喜欢的是使用):try
except
os.access
尝试打开文件:
打开文件将始终验证文件是否存在。你可以像这样制作一个函数:
def File_Existence(filepath): f = open(filepath) return True
如果为 False,它将使用未处理的 IOError 停止执行 或 OSError。要捕获异常, 您必须使用 try except 子句。当然,你总是可以 像这样使用 except' 语句(感谢 Hsandt 让我思考):
try
def File_Existence(filepath): try: f = open(filepath) except IOError, OSError: # Note OSError is for later versions of Python return False return True
用:
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
用:
os.access(path, mode)
这将检查您是否有权访问该文件。它将检查权限。根据 os.py 文档,键入 ,它将检查路径是否存在。但是,使用此功能会造成安全漏洞,因为有人可能会利用检查权限和打开文件之间的时间来攻击您的文件。相反,您应该直接打开文件,而不是检查其权限。(EAFP 与 LBYP)。如果您之后不打算打开该文件,而只是检查它的存在,那么您可以使用它。
os.F_OK
无论如何,这里:
>>> 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)
if os.path.isfile(path_to_file):
try:
open(path_to_file)
pass
except IOError as e:
print "Unable to open file"
引发异常被认为是可以接受的,而 Pythonic, 程序中的流量控制方法。考虑处理缺失 文件。在此情况下,IOError 异常将是 如果文件存在但用户没有读取权限,则引发。
评论
用:
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
有关参考,另请参阅如何检查文件是否存在且没有异常?。
如果需要高级操作,请使用 .shutil
评论
os.path.exists
os.path.isfile
import os.path
def isReadableFile(file_path, file_name):
full_path = file_path + "/" + file_name
try:
if not os.path.exists(file_path):
print "File path is invalid."
return False
elif not os.path.isfile(full_path):
print "File does not exist."
return False
elif not os.access(full_path, os.R_OK):
print "File cannot be read."
return False
else:
print "File can be read."
return True
except IOError as ex:
print "I/O error({0}): {1}".format(ex.errno, ex.strerror)
except Error as ex:
print "Error({0}): {1}".format(ex.errno, ex.strerror)
return False
#------------------------------------------------------
path = "/usr/khaled/documents/puzzles"
fileName = "puzzle_1.txt"
isReadableFile(path, fileName)
评论
isReadableFile(path,fileName)
True
如何在不使用 try 语句的情况下使用 Python 检查文件是否存在?
现在从 Python 3.4 开始可用,导入并实例化带有文件名的对象,并检查方法(请注意,对于指向常规文件的符号链接,这也返回 True):Path
is_file
>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False
如果您使用的是 Python 2,则可以从 pypi、pathlib2
向后移植 pathlib 模块,或者从模块中检查:isfile
os.path
>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False
现在,上面可能是这里最好的实用直接答案,但存在竞争条件的可能性(取决于您要完成的任务),并且底层实现使用 ,但 Python 在其实现中无处不在。try
try
因为 Python 无处不在,所以真的没有理由避免使用它的实现。try
但这个答案的其余部分试图考虑这些警告。
更长、更迂腐的答案
从 Python 3.4 开始可用,请使用 中的新对象。请注意,这并不完全正确,因为目录不是文件(除非在 unix 意义上,一切都是文件)。Path
pathlib
.exists
>>> 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
context manager),它在语义上以更少的行数执行完全相同的事情,同时(至少在表面上)满足了原始要求以避免语句: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,您可以滚动自己的 ,但没有 will 比 with 更冗长。我确实相信这实际上是唯一一个在 Python 3.4 之前可以应用于 Python 的任何级别的 try 不使用 try
的答案,因为它使用上下文管理器来代替:suppress
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
其他不符合“不尝试”要求的选项:
is文件
import os
os.path.isfile(path)
从文档中:
os.path.isfile(path)
如果 path 是现有的常规文件,则返回 True。这遵循符号 链接,因此对于同一路径,两者都可以为 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:
with open(path) as f:
f.read()
except OSError:
pass
操作系统.access
可用于 Unix 和 Windows 的是 ,但要使用,您必须传递标志,并且它不区分文件和目录。这更用于测试真正的调用用户是否在提升的权限环境中具有访问权限:os.access
import os
os.access(path, os.F_OK)
它还存在与 相同的竞争条件问题。从文档中:isfile
注意: 使用 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" # 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
KeyboardInterrupt
SystemExit
这似乎鼓励用户采用不良做法。
下面是用于 Linux 命令行环境的单行 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
在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 解决方案。你可以用它做更多的事情。如果你只需要检查存在性,优势就没有那么大了。
我是一个已经存在了大约 10 年的软件包的作者,它有一个直接解决这个问题的功能。基本上,如果您使用的是非 Windows 系统,它用于访问 .但是,如果您使用的是 Windows,它会使用高效的文件系统遍历器进行复制。Popen
find
find
代码本身不使用块...除了确定操作系统,从而引导您到“Unix”风格或手工构建。时序测试表明,在确定操作系统方面速度更快,所以我确实在那里使用了一个(但在其他地方没有)。try
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
您可以使用 os.listdir 来检查文件是否在某个目录中。
import os
if 'file.ext' in os.listdir('dirpath'):
#code
评论
再添加一个细微的变化,这在其他答案中并没有完全反映出来。
这将处理 being 或空字符串的情况。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)
return x
if (x)
x
os.path.isfile(..)
os.path.isfile(None)
引发异常,这就是我添加 if 检查的原因。我可能只是把它包装在一个尝试/除了中,但我觉得这样更明确。
return file_path and os.path.isfile(file_path)
使用 和 测试文件和文件夹os.path.isfile()
os.path.isdir()
os.path.exists()
假设“path”是有效路径,下表显示了每个函数为文件和文件夹返回的内容:
您还可以测试文件是否是用于获取扩展名的某种类型的文件(如果您还不知道)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
如何在不使用 try 语句的情况下检查文件是否存在?
在 2016 年,这仍然可以说是检查文件是否存在以及是否为文件的最简单方法:
import os
os.path.isfile('./file.txt') # Returns True if exists, else False
isfile
实际上只是一个内部使用和下面的辅助方法。这是一种较低级别的方法,可为您提供有关文件、目录、套接字、缓冲区等的详细信息。有关 os.stat 的更多信息,请点击此处os.stat
stat.S_ISREG(mode)
os.stat
注意:但是,此方法不会以任何方式锁定文件,因此您的代码可能容易受到“检查时间到使用时间”(TOCTTOU)错误的影响。
因此,引发异常被认为是程序中可接受的 Python 流控制方法。应该考虑使用 IOErrors 处理丢失的文件,而不是语句(只是一个建议)。if
尽管几乎所有可能的方法都已在现有答案中列出(至少一种)(例如,添加了 Python 3.4 特定的东西),但我会尝试将所有内容组合在一起。
注意:我将要发布的每段 Python 标准库代码都属于 3.5.3 版本。
问题陈述:
检查文件(可争辩:也是文件夹(“特殊”文件)?)是否存在
不要使用 try / except / else / finally 块
可能的解决方案:
1. [Python.Docs]:os.path.exists(路径)
还要检查其他函数系列成员,如 os.path.isfile、os.path.isdir、os.path.lexists,了解其行为是否略有不同:
如果 path 引用现有路径或打开的文件描述符,则返回。返回断开的符号链接。在某些平台上,如果未授予对请求的文件执行 os.stat() 的权限,即使路径实际存在,此函数也可能会返回。
True
False
False
一切都很好,但是如果遵循导入树:
os.path - posixpath.py (ntpath.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] 周围的一个尝试/除外块:os.stat(path, *, dir_fd=None, follow_symlinks=True)。因此,您的代码是 try / except free,但在帧堆栈的较低位置(至少)有一个这样的块。这也适用于其他函数(包括 os.path.isfile)。
1.1. [Python.Docs]:pathlib - Path.is_file()
这是一种更高级(更[维基词典]:Pythonic)处理路径的方式,但是
在引擎盖下,它做完全相同的事情(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.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 语句指出:
3. 文件系统遍历函数
在结果中搜索匹配项:
[Python.Docs]:os.listdir(path='.')(或 Python v3.5+ 上的 [Python.Docs]: os.scandir(path='.'),向后移植:[PyPI]:scandir)
在引擎盖下,两者都使用:
Nix:[Man7]:OPENDIR(3) / [Man7]:READDIR(3) / [Man7]:CLOSEDIR(3)
获胜:[MS.学习]: FindFirstFileW 函数 (fileapi.h) / [MS.学习]: FindNextFileW 函数 (fileapi.h) / [MS.学习]: FindClose 函数 (fileapi.h)
通过 [GitHub]: python/cpython - (main) cpython/Modules/posixmodule.c
使用 scandir() 而不是 listdir() 可以显著提高同样需要文件类型或文件属性信息的代码的性能,因为 os.如果操作系统在扫描目录时提供此信息,则 DirEntry 对象会公开此信息。所有操作系统。DirEntry 方法可以执行系统调用,但 is_dir() 和 is_file() 通常只需要对符号链接进行系统调用;操作系统。DirEntry.stat() 在 Unix 上始终需要系统调用,但在 Windows 上只需要一个符号链接。
[Python.Docs]:os.walk(top, topdown=True, onerror=None, followlinks=False)
- 使用 os.listdir(os.scandir,如果可用)
[Python.Docs]:glob.iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False, include_hidden=False) (或其前身:glob.glob)
- 本身似乎不是一个遍历函数(至少在某些情况下),但它仍然使用 os.listdir
由于这些遍历文件夹,(在大多数情况下)它们对于我们的问题效率低下(也有例外,例如非通配符通配符 - 正如@ShadowRanger指出的那样),所以我不会坚持使用它们。更不用说在某些情况下,可能需要对文件名进行处理。
4. [Python.Docs]:os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True)
它的行为接近 os.path.exists(实际上它更广泛,主要是因为第 2个参数)。
用户权限可能会限制文件的“可见性”,如文档所述:
...测试调用用户是否具有对路径的指定访问权限。应F_OK mode 来测试路径...
安全注意事项:
使用 access() 检查用户是否被授权,例如,在实际打开文件之前,使用 open() 会创建一个安全漏洞,因为用户可能会利用检查和打开文件之间的短时间间隔来操作它。
os.access("/tmp", os.F_OK)
由于我也使用 C 语言,所以我也使用这种方法,因为在后台,它调用本机 APIs(再次,通过“${PYTHON_SRC_DIR}/Modules/posixmodule.c”),但它也为可能的用户错误打开了大门,并且它不像其他变体那样像 Pythonic。所以,除非你知道你在做什么,否则不要使用它:
Nix:[Man7]:访问(2)
警告: 例如,使用这些调用来检查用户是否有权打开一个文件,然后再使用 open(2) 打开文件会产生一个安全漏洞,因为用户可能会利用检查和打开文件之间的短时间间隔来操作它。因此,应避免使用此系统调用。
如上所述,强烈建议不要使用这种方法(尤其是在 Nix 上)。
注意:也可以通过 [Python.Docs] 调用原生 API s: ctypes - Python 的外部函数库,但在大多数情况下它更复杂。在使用 CTypes 之前,请检查 [SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati的答案)。
(特定于 Win):由于 vcruntime###.dll (msvcr###.dll 对于较旧的 VStudio 版本 - 我将其称为 UCRT)导出 [MS.学习]:_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 3 和 Python 2(尽管 [维基百科]:它们之间存在 Unicode 相关差异 - [SO]:将 utf-16 字符串传递给 Windows 函数(@CristiFati的答案))
虽然这针对一个非常具体的领域,但在之前的任何答案中都没有提到
Linux (Ubuntu ([Wikipedia]: Ubuntu version history) 16 x86_64 (pc064)) 对应物也是如此:
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
注意:
取而代之的是,硬编码 libc.so (LibC) 的路径 (“/lib/x86_64-linux-gnu/libc.so.6”),该路径可能(并且很可能)因系统而异,None (或空字符串) 可以传递给 CDLL 构造函数 (
ctypes.CDLL(None).access(b“/tmp”, os.F_OK)
)。根据 [Man7]: DLOPEN(3):如果 filename 为 NULL,则返回的句柄用于 main 程序。当给定给 dlsym(3) 时, 这个句柄会导致搜索 符号,后跟所有加载的共享对象 程序启动,然后 dlopen() 加载的所有共享对象 旗帜RTLD_GLOBAL。
主(当前)程序(python)与LibC链接,因此将加载其符号(包括访问)
这必须小心处理,因为 main、Py_Main 和(所有)其他功能都可用;打电话给他们可能会产生灾难性的影响(对当前程序)
这也不适用于 Windows(但这没什么大不了的,因为 UCRT 位于“%SystemRoot%\System32”中,默认情况下位于 %PATH% 中)。我想更进一步,在 Windows 上复制这种行为(并提交补丁),但事实证明,[MS.学习]:GetProcAddress 函数 (libloaderapi.h) 只能“看到”导出的符号,因此除非有人将主可执行文件中的函数声明为(为什么普通人会这样做?),否则主程序是可加载的,但它几乎无法使用
__declspec(dllexport)
5. 具有文件系统功能的第三方模块
最有可能的是,将依赖上述方法之一(可能略有自定义)。
一个例子是(再次,特定于 Win)[GitHub]: mhammond/pywin32 - Python for Windows (pywin32) Extensions,它是 WinAPI的 Python 包装器。
但是,由于这更像是一种解决方法,因此我到此为止。
6. SysAdmin方法
我认为这是一个(蹩脚的)解决方法(gainarie):使用 Python 作为包装器来执行 shell 命令:
赢:
(py35x64_test) [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q000082831]> "e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\Temp\" > nul 2>&1'))" 0 (py35x64_test) [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q000082831]> "e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os; print(os.system('dir /b \"C:\\Windows\\Temp.notexist\" > nul 2>&1'))" 1
Nix ([Wikipedia]: 类 Unix) - 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 块,因为它们可以防止您遇到一系列令人讨厌的问题
我能想到的一个可能的反例是性能:这样的块很昂贵,所以尽量不要把它们放在每秒应该运行数十万次的代码中(但由于(在大多数情况下)它涉及磁盘访问,所以情况并非如此)
评论
os.scandir
的,所以它现在是懒惰的;要在包含 10M 个文件的目录中获得第一次命中,您只需扫描直到到达第一个命中。即使在 3.6 之前,如果您使用没有任何通配符的方法,该函数也很聪明:它知道您只能命中一次,因此它将通配简化为仅 os.path.isdir 或 os.path.lexists
(取决于路径是否以 结尾)。glob
/
os.path.isdir
os.path.lexist
如果您已经出于其他目的导入了 NumPy,则无需导入其他库,如 、 、 等。pathlib
os
paths
import numpy as np
np.DataSource().exists("path/to/your/file")
这将根据其存在返回 true 或 false。
日期: 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']}
检查文件或目录是否存在
您可以按照以下三种方式操作:
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.使用存在
注 2:用于文件和目录os.path.exists
import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) # True if directory exists
3. 方法(包含在 Python 3+ 中,可使用 Python 2 的 pip 安装)pathlib.Path
from pathlib import Path
Path(filename).exists()
用:
import os
# For testing purposes the arguments defaulted to the current folder and file.
# returns True if file found
def file_exists(FOLDER_PATH='../', FILE_NAME=__file__):
return os.path.isdir(FOLDER_PATH) \
and os.path.isfile(os.path.join(FOLDER_PATH, FILE_NAME))
它基本上是文件夹检查,然后使用 os.path.join 使用正确的目录分隔符进行文件检查。
'Path' 对象的 exists() 和 is_file() 方法可用于检查给定路径是否存在并且是文件。
Python 3 程序检查文件是否存在:
# File name: check-if-file-exists.py
from pathlib import Path
filePath = Path(input("Enter path of the file to be found: "))
if filePath.exists() and filePath.is_file():
print("Success: File exists")
else:
print("Error: File does not exist")
输出:
$ python3 check-if-file-exists.py
输入要查找的文件的路径:/Users/macuser1/stack-overflow/index.html
成功:文件存在
$ python3 check-if-file-exists.py
输入要找到的文件路径:hghjg jghj
错误:文件不存在
使用 os.path.exists() 检查文件是否存在:
def fileAtLocation(filename,path):
return os.path.exists(path + filename)
filename="dummy.txt"
path = "/home/ie/SachinSaga/scripts/subscription_unit_reader_file/"
if fileAtLocation(filename,path):
print('file found at location..')
else:
print('file not found at location..')
评论
TL;
DR 答案是:使用 pathlib
模块
Pathlib 可能是几乎所有文件操作最现代、最方便的方式。对于文件或文件夹的存在,一行代码就足够了。如果 file 不存在,则不会引发任何异常。
from pathlib import Path
if Path("myfile.txt").exists(): # works for both file and folders
# do your cool stuff...
该模块是在 Python 3.4 中引入的,因此您需要拥有 Python 3.4+。这个库让你在处理文件和文件夹时的生活更轻松,而且使用起来很漂亮。以下是有关它的更多文档: pathlib — 面向对象的文件系统路径。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.
评论
p.exists()
另一个可能的选择是使用 os.listdir() 检查文件名是否在目录中:
import os
if 'foo.txt' in os.listdir():
# Do things
如果是,则返回 true,如果不是,则返回 false。
评论
if Path('foo.txt') in Path().iterdir()
这就是我如何在一个文件夹中找到文件列表(在这些图像中)并在文件夹(带有子文件夹)中搜索它:
# This script concatenates JavaScript files into a unified JavaScript file to reduce server round-trips
import os
import string
import math
import ntpath
import sys
#import pyodbc
import gzip
import shutil
import hashlib
# BUF_SIZE is totally arbitrary, change for your app!
BUF_SIZE = 65536 # Let’s read stuff in 64 kilobyte chunks
# Iterate over all JavaScript files in the folder and combine them
filenames = []
shortfilenames = []
imgfilenames = []
imgshortfilenames = []
# Get a unified path so we can stop dancing with user paths.
# Determine where files are on this machine (%TEMP% directory and application installation directory)
if '.exe' in sys.argv[0]: # if getattr(sys, 'frozen', False):
RootPath = os.path.abspath(os.path.join(__file__, "..\\"))
elif __file__:
RootPath = os.path.abspath(os.path.join(__file__, "..\\"))
print ("\n storage of image files RootPath: %s\n" %RootPath)
FolderPath = "D:\\TFS-FARM1\\StoneSoup_STS\\SDLC\\Build\\Code\\StoneSoup_Refactor\\StoneSoupUI\\Images"
print ("\n storage of image files in folder to search: %s\n" %FolderPath)
for root, directories, filenames2 in os.walk(FolderPath):
for filename in filenames2:
fullname = os.path.join(root, filename)
filenames.append(fullname)
shortfilenames.append(filename)
for i, fname in enumerate(shortfilenames):
print("%s - %s" % (i+1, fname))
for root, directories, filenames2 in os.walk(RootPath):
for filename in filenames2:
fullname = os.path.join(root, filename)
imgfilenames.append(fullname)
imgshortfilenames.append(filename)
for i, fname in enumerate(imgshortfilenames):
print("%s - %s" % (i+1, fname))
for i, fname in enumerate(imgshortfilenames):
if fname in shortfilenames:
print("%s - %s exists" % (i+1, fname))
else:
print("%s - %s ABSENT" % (i+1, fname))
评论