[Python] 如何检查文件是否存在?


Answers

你有os.path.exists函数:

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

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

Question

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




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




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.




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

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

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




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



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



import os.path

if os.path.isfile(filepath):



2017/12/22

虽然几乎所有可能的方法都已经被列入(至少一个)现有的答案中(例如添加了Python 3.4特定的东西),但我会尝试将所有内容组合在一起。

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

问题陈述

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

可能的方案

  1. [Python]:os.path。 存在路径 (也检查其他函数家族成员,如os.path.isfileos.path.isdiros.path.lexists用于稍微不同的行为)

    os.path.exists(path)
    

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

    一切顺利,但如果按照导入树:

    • 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
        

    它只是围绕os.stat()一个try/exceptos.stat() os.stat() 。 所以,你的代码try/except免费,但在framestack中更低(至少)有一个这样的块。 这也适用于其他funcs( 包括 os.path.isfile )。

    1.1。 [Python]:pathlib.Path。 is_file ()

    • 这是一种处理路径的发烧友(和更多python ic), 但是
    • 在引擎盖下,它完全一样的东西( 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]:使用语句上下文管理器 。 或者:

    • 创建一个:

      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 ...)
      
      • 其用法 - 我将复制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]:contextlib。 抑制*例外 - 这是专门为有选择地抑制例外而设计的


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

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

  3. 文件系统遍历功能(并搜索匹配项目的结果)


    由于这些迭代遍历文件夹(在大多数情况下),它们对于我们的问题效率不高(有一些例外情况,如非阴影循环 - 正如@ ShadowRanger所指出的那样),所以我不会坚持它们。 更不用说在某些情况下,可能需要文件名处理。

  4. [Python]:os。 访问path,mode,*,dir_fd = None,effective_ids = False,follow_symlinks = True ),其行为接近os.path.exists (实际上它更宽,主要是因为第2个参数)

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

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

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

    因为我也在C中工作,所以我也使用这种方法,因为它背后调用了本机API (同样通过“ $ {PYTHON_SRC_DIR} /Modules/posixmodule.c ”),但它也为可能的用户打开了一扇门错误 ,它不像其他变体那样是Python ic。 所以,正如@AaronHall正确指出的那样,除非你知道你在做什么,否则不要使用它:

    注意 :通过[Python]也可以调用本机API 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上工作 (尽管它们之间存在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的路径( “/lib/x86_64-linux-gnu/libc.so.6” ),这可能(也很可能会)跨系统变化, None (或空字符串)可以传递给CDLL构造函数( ctypes.CDLL(None).access(b"/tmp", os.F_OK) )。 根据[男子]:DLOPEN(3)

      如果文件名为NULL,则返回的句柄用于主程序。 当提供给dlsym ()时,该句柄将导致在主程序中搜索一个符号,然后在程序启动时加载所有共享对象,然后使用标志RTLD_GLOBAL通过dlopen ()加载所有共享对象。

      • Main(当前)程序( python )与libc链接,因此它的符号(包括access )将被加载
      • 这必须小心处理,因为像mainPy_Main和(所有)其他函数都是可用的; 称他们可能会造成灾难性后果(对当前的计划)
      • 这并不适用于Win (但这并不重要,因为msvcrt.dll位于%SystemRoot%\ System32中,默认为%PATH% )。 我想进一步研究并在Win上复制这种行为(并提交补丁),但事实证明, [MSDN]:GetProcAddress函数只能“看到” 导出的符号,因此除非有人在主可执行文件中声明函数为__declspec(dllexport) (为什么地球上的普通人会这样做?),主程序是可加载的,但几乎不可用
  5. 安装一些具有文件系统功能的第三方模块

    最有可能的是,将依赖于上述方式之一(可能稍有定制)。
    一个例子是(同样,特定于Win[GitHub]:Python for Windows(pywin32)扩展 ,它是WINAPI上Python封装。

    但是,因为这更像是一种解决方法,所以我在这里停下来。

  6. 另一个(跛脚)解决方法( 增益 )是(我喜欢称之为) sysadmin方法:使用Python作为包装来执行shell命令

    • Win

      (py35x64_test) e:\Work\Dev\\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\\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
      
    • LnxUbtu ):

      [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
      

底线

  • 使用try / except / else / finally块,因为它们可以防止您遇到一系列令人讨厌的问题。 我能想到的一个反例就是性能:这种块的成本很高,所以尽量不要将它们放在代码中,它应该每秒运行几十万次(但是由于(大多数情况下)它涉及磁盘访问,情况并非如此)。

最后说明

  • 我会尽力让它保持最新状态,欢迎提出任何建议,我会整合任何有用的东西,并将其纳入答案



如果该文件是用于打开的,则可以使用以下技术之一:

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



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

我希望这是有帮助的。




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可以更轻松地导航并执行操作系统的标准操作。

另请参阅share

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




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



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




似乎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'

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






Links