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


Answers

你有os.path.exists函數:

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

這對文件和目錄都返回True ,但你可以使用os.path.isfile來測試它是否是一個特定的文件。 它遵循符號鏈接。

Question

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




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

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




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



你可以試試這個(更安全):

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




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




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正確指出的,除非你知道你在做什麼,否則不要使用它:

    注意 :調用本機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上工作 (儘管它們之間存在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 ()時,該句柄將導致在主程序中搜索一個符號,然後在程序啟動時加載所有共享對象,然後通過dlopen ()加載標誌為RTLD_GLOBAL的所有共享對象。

      • 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塊,因為它們可以防止您遇到一系列令人討厭的問題。 我能想到的一個反例就是性能:這種塊的成本很高,所以盡量不要將它們放在代碼中,它應該每秒運行數十萬次(但是由於(大多數情況下)它涉及磁盤訪問,情況並非如此)。

最後說明

  • 我會盡力讓它保持最新狀態,歡迎提出任何建議,我會整合任何有用的東西,並將其納入答案



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




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

I hope this is helpful.




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




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




import os.path

if os.path.isfile(filepath):



If the file is for opening you could use one of the following techniques:

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



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