it-swarm-vi.tech

Làm cách nào để kiểm tra xem một tệp có tồn tại mà không có ngoại lệ không?

Làm cách nào để xem một tập tin có tồn tại hay không, mà không sử dụng câu lệnh try ?

4981
spence91

Nếu lý do bạn đang kiểm tra là để bạn có thể làm điều gì đó như if file_exists: open_it(), thì an toàn hơn là sử dụng try xung quanh nỗ lực mở nó. Kiểm tra và sau đó mở có nguy cơ tệp bị xóa hoặc di chuyển hoặc một cái gì đó giữa khi bạn kiểm tra và khi bạn cố gắng mở nó.

Nếu bạn không định mở tệp ngay lập tức, bạn có thể sử dụng os.path.isfile

Trả về True nếu đường dẫn là một tệp thông thường hiện có. Điều này tuân theo các liên kết tượng trưng, ​​vì vậy cả islink ()isfile () có thể đúng cho cùng một đường dẫn.

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

nếu bạn cần chắc chắn đó là một tập tin.

Bắt đầu với Python 3.4, mô đun pathlib cung cấp cách tiếp cận hướng đối tượng (được nhập vào pathlib2 trong Python 2.7):

from pathlib import Path

my_file = Path("/path/to/file")
if my_file.is_file():
    # file exists

Để kiểm tra một thư mục, hãy làm:

if my_file.is_dir():
    # directory exists

Để kiểm tra xem một đối tượng Path có tồn tại độc lập hay không, đó là tệp hay thư mục, hãy sử dụng exists():

if my_file.exists():
    # path exists

Bạn cũng có thể sử dụng resolve(strict=True) trong khối try:

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

Bạn có chức năng os.path.exists :

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

Điều này trả về True cho cả tệp và thư mục nhưng thay vào đó bạn có thể sử dụng

os.path.isfile(file_path)

để kiểm tra nếu đó là một tập tin cụ thể. Nó theo symlink.

1913
PierreBdR

Không giống như isfile() , exists() sẽ trả về True cho các thư mục.
[.__.] Vì vậy, tùy thuộc vào việc bạn chỉ muốn các tệp đơn giản hay cả các thư mục, bạn sẽ sử dụng isfile() hoặc exists(). Đây là một đầu ra REPL đơn giản.

>>> print os.path.isfile("/etc/password.txt")
True
>>> print os.path.isfile("/etc")
False
>>> print os.path.isfile("/does/not/exist")
False
>>> print os.path.exists("/etc/password.txt")
True
>>> print os.path.exists("/etc")
True
>>> print os.path.exists("/does/not/exist")
False
885
bortzmeyer
import os.path

if os.path.isfile(filepath):
543
Paul

Sử dụng os.path.isfile() với os.access() :

import os
import os.path

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"
268
Yugal Jindle
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
248
benefactual

Mặc dù hầu hết mọi cách có thể đã được liệt kê trong (ít nhất một trong số) các câu trả lời hiện có (ví dụ Python 3,4 nội dung cụ thể đã được thêm vào), tôi sẽ cố gắng nhóm mọi thứ lại với nhau.

Lưu ý : mọi phần của Python mã thư viện chuẩn mà tôi sẽ đăng, thuộc về phiên bản 3.5.3 .

Báo cáo sự cố :

  1. Kiểm tra tệp (arguable: thư mục (tệp "đặc biệt")?)
  2. Không sử dụng thử/ngoại trừ/other/cuối cùng khối

Các giải pháp có thể :

  1. [Python 3]: os.path. tồn tại (path) (cũng kiểm tra chức năng khác các thành viên trong gia đình như os.path.isfile, os.path.isdir, os.path.lexists cho các hành vi hơi khác nhau)

    os.path.exists(path)
    

    Trả về True if path đề cập đến một đường dẫn hiện có hoặc một mô tả tệp đang mở. Trả về False cho các liên kết tượng trưng bị hỏng. Trên một số nền tảng, chức năng này có thể trả về False nếu quyền không được cấp để thực thi os.stat () trên tệp được yêu cầu, ngay cả khi path tồn tại trên thực tế .

    Tất cả đều tốt, nhưng nếu theo cây nhập khẩu:

    • os.path - posixpath.py (ntpath.py)

      • genericpath.py, dòng ~ # 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
        

    nó chỉ là một thử/ngoại trừ chặn xung quanh [Python 3]: os. stat (path, *, dir_fd = Không , follow_symlinks = Đúng) . Vì vậy, mã của bạn là thử/trừ miễn phí, nhưng thấp hơn trong framestack có (ít nhất) một khối như vậy. Điều này cũng áp dụng cho các func khác ( bao gồm os.path.isfile).

    1.1. [Python 3]: Đường dẫn. is_file ()

    • Đó là cách xử lý đường dẫn (và hơn thế nữa python ic), nhưng
    • Dưới mui xe, nó thực hiện chính xác điều tương tự (pathlib.py, dòng ~ # 13 =):

      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 3]: Với Trình quản lý bối cảnh câu lệnh . Hoặc:

    • Tạo một cái:

      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 ...)
      
      • Và cách sử dụng của nó - Tôi sẽ sao chép hành vi os.path.isfile (lưu ý rằng đây chỉ là để thể hiện mục đích, đừng không cố gắng viết mã như vậy cho sản xuất):

        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
        
    • Sử dụng [Python 3]: bối cảnh. kìm nén (* ngoại lệ) - đó là cụ thể được thiết kế để loại bỏ ngoại lệ có chọn lọc


    [.__.] Nhưng, dường như chúng được bao bọc thử/ - ngoại trừ/khác/cuối cùng chặn, như [Python 3]: với statement tuyên bố:

    Điều này cho phép phổ biến thử ... ngoại trừ ... cuối cùng các mẫu sử dụng được gói gọn để sử dụng lại thuận tiện.

  3. Các chức năng truyền tải hệ thống tệp (và tìm kiếm kết quả cho (các) mục phù hợp)


    [.__.] Vì các lần lặp này qua các thư mục, (trong hầu hết các trường hợp), chúng không hiệu quả cho vấn đề của chúng tôi (có trường hợp ngoại lệ, như không ký tự đại diện global bing - như @ShadowRanger đã chỉ ra), vì vậy Tôi sẽ không nhấn mạnh vào họ. Chưa kể rằng trong một số trường hợp, xử lý tên tệp có thể được yêu cầu.

  4. [Python 3]: os. truy cập (đường dẫn, chế độ, *, dir_fd = Không có, có hiệu lực = Sai, theo dõi_symlinks = True) có hành vi gần với os.path.exists (thực ra nó rộng hơn, chủ yếu là do 2thứ tranh luận)

    • quyền người dùng có thể hạn chế tệp "khả năng hiển thị" như trạng thái tài liệu: [.__.]

      ... kiểm tra xem người dùng gọi có quyền truy cập được chỉ định vào path. mode nên là F_OK để kiểm tra sự tồn tại của đường dẫn ...

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

    Vì tôi cũng làm việc trong C, tôi cũng sử dụng phương pháp này vì dưới mui xe, nó gọi bản địa API s (một lần nữa, thông qua "$ {PYTHON_SRC_DIR} /Modules/poseixmodule.c"), nhưng nó cũng mở một cổng cho khả năng lỗi người dùng và không phải là Python ic như các biến thể khác. Vì vậy, như @AaronHall đã chỉ ra một cách đúng đắn, đừng sử dụng nó trừ khi bạn biết bạn đang làm gì:

    Lưu ý : gọi riêng API s cũng có thể thông qua [Python 3]: ctypes - Một thư viện hàm nước ngoài cho Python , nhưng trong hầu hết các trường hợp, nó phức tạp hơn.

    (Win cụ thể): Vì vcr nb * (msvcr * ) . dll xuất a [MS.Docs]: _access, _waccess họ chức năng, đây là một ví dụ:

    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.notexist", os.F_OK)
    -1
    

    Ghi chú :

    • Mặc dù đó không phải là một cách thực hành tốt, tôi đang sử dụng os.F_OK trong cuộc gọi, nhưng đó chỉ là sự rõ ràng (giá trị của nó là 0 )
    • Tôi đang sử dụng _ waccess để cùng một mã hoạt động trên PythonPython2 (mặc dù nicode sự khác biệt có liên quan giữa họ)
    • Mặc dù mục tiêu này nhắm đến một khu vực rất cụ thể, nó không được đề cập trong bất kỳ câu trả lời nào trước đó


    [.__.] Lnx (btu (16 x64)) cũng là đối tác:

    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"/tmp.notexist", os.F_OK)
    -1
    

    Ghi chú :

    • Thay vào đó, mã hóa libc 'đường dẫn ("/ lib/x86_64-linux-gnu/libc.so.6") có thể (và rất có thể, sẽ) khác nhau giữa các hệ thống , Không (hoặc chuỗi trống) có thể được chuyển đến CDLL constructor (ctypes.CDLL(None).access(b"/tmp", os.F_OK) ). Theo [man7]: DLOPEN (3) :

      Nếu tên tệp là NULL, thì xử lý được trả về là dành cho chương trình chính. Khi được trao cho dlsym (), điều khiển này gây ra tìm kiếm biểu tượng trong chương trình chính, theo sau là tất cả các đối tượng được chia sẻ được tải khi khởi động chương trình, sau đó tất cả các đối tượng được chia sẻ được tải bởi dlopen () với cờ RTLD_GLOBAL .

      • Chương trình chính (hiện tại) (python) được liên kết với libc, vì vậy các ký hiệu của nó (bao gồm access) sẽ được tải
      • Điều này phải được xử lý cẩn thận, vì các chức năng như main, Py_Main và (tất cả) các thứ khác đều khả dụng; gọi họ có thể có tác động thảm họa (trên chương trình hiện tại)
      • Điều này cũng không áp dụng cho Win (nhưng đó không phải là vấn đề lớn, vì msvcrt.dll nằm ở "% SystemRoot%\System32" đó là trong % PATH% theo mặc định). Tôi muốn đưa mọi thứ đi xa hơn và sao chép hành vi này trên Win (và gửi một bản vá), nhưng khi nó bật ra, [MS.Docs]: Hàm GetProcAddress only "thấy Các ký hiệu " đã xuất , vì vậy trừ khi có ai đó khai báo các hàm trong tệp thực thi chính là __declspec(dllexport) (tại sao trên Trái đất chính quy người sẽ làm đó?), chương trình chính có thể tải nhưng khá nhiều không sử dụng được
  5. Cài đặt một số mô-đun của bên thứ ba với khả năng hệ thống tập tin

    Nhiều khả năng, sẽ dựa vào một trong những cách trên (có thể với các tùy chỉnh nhỏ).
    [.__.] Một ví dụ sẽ là (một lần nữa, Win cụ thể) [GitHub]: mhammond/pywin32 - Python cho Windows (pywin32) Tiện ích mở rộng , đó là một Python trình bao bọc WINAPI s.

    Nhưng, vì đây giống như một cách giải quyết hơn, tôi dừng lại ở đây.

  6. Một cách giải quyết khác (khập khiễng) (gainarie) là (như tôi muốn gọi nó,) sysadmin cách tiếp cận: sử dụng Python làm trình bao bọc để thực thi Lệnh Shell

    • Thắng:

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

      [[email protected]:~]> python3 -c "import os; print(os.system('ls \"/tmp\" > /dev/null 2>&1'))"
      0
      [[email protected]:~]> python3 -c "import os; print(os.system('ls \"/tmp.notexist\" > /dev/null 2>&1'))"
      512
      

Dòng dưới cùng :

  • Làm sử dụng thử/ngoại trừ/khác/cuối cùng khối, vì chúng có thể ngăn bạn gặp phải một loạt vấn đề khó chịu. Một ví dụ ngược lại mà tôi có thể nghĩ đến là hiệu năng: các khối như vậy rất tốn kém, vì vậy hãy cố gắng không đặt chúng vào mã mà nó phải chạy hàng trăm nghìn lần mỗi giây (nhưng vì (trong hầu hết các trường hợp) nó liên quan đến truy cập đĩa, nó sẽ không phải là trường hợp).

Ghi chú cuối cùng :

  • Tôi sẽ cố gắng cập nhật, mọi đề xuất đều được chào đón, tôi sẽ kết hợp mọi thứ hữu ích sẽ đưa ra câu trả lời
222
CristiFati

Đây là cách đơn giản nhất để kiểm tra nếu một tập tin tồn tại. Chỉ bởi vì tệp tồn tại khi bạn kiểm tra không đảm bảo rằng nó sẽ ở đó khi bạn cần mở nó.

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

Python 3,4+ có mô-đun đường dẫn hướng đối tượng: pathlib . Sử dụng mô-đun mới này, bạn có thể kiểm tra xem một tệp có tồn tại như thế này không:

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

Bạn có thể (và thường nên) vẫn sử dụng khối try/except khi mở tệp:

try:
    with p.open() as f:
        # do awesome stuff
except OSError:
    print('Well darn.')

Mô-đun pathlib có rất nhiều thứ hay ho trong đó: tiện ích toàn cầu, kiểm tra chủ sở hữu tệp, tham gia đường dẫn dễ dàng hơn, v.v ... Thật đáng để kiểm tra. Nếu bạn đang dùng Python cũ (phiên bản 2.6 trở lên), bạn vẫn có thể cài đặt pathlib với pip:

# installs pathlib2 on older Python versions
# the original third-party module, pathlib, is no longer maintained.
pip install pathlib2

Sau đó nhập nó như sau:

# Older Python versions
import pathlib2 as pathlib
132
Cody Piersall

Thích tuyên bố thử. Nó được coi là phong cách tốt hơn và tránh các điều kiện chủng tộc.

Đừng lấy từ của tôi cho nó. Có rất nhiều hỗ trợ cho lý thuyết này. Đây là một cặp vợ chồng:

116
pkoch

Làm cách nào để kiểm tra xem một tệp có tồn tại hay không, sử dụng Python mà không sử dụng câu lệnh try?

Hiện có sẵn từ Python 3.4, nhập và khởi tạo một đối tượng Path với tên tệp và kiểm tra phương thức is_file (lưu ý rằng điều này cũng trả về True cho các liên kết tượng trưng chỉ vào các tệp thông thường):

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

Nếu bạn đang dùng Python 2, bạn có thể nhập lại mô-đun pathlib từ pypi, pathlib2 hoặc kiểm tra isfile từ mô-đun os.path:

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

Bây giờ ở trên có lẽ là câu trả lời trực tiếp thực dụng tốt nhất ở đây, nhưng có khả năng xảy ra tình trạng chủng tộc (tùy thuộc vào những gì bạn đang cố gắng thực hiện) và thực tế là việc triển khai cơ bản sử dụng try, nhưng Python sử dụng try ở mọi nơi thực hiện.

Vì Python sử dụng try ở mọi nơi, nên thực sự không có lý do gì để tránh việc triển khai sử dụng nó.

Nhưng phần còn lại của câu trả lời này cố gắng xem xét những cảnh báo này.

Câu trả lời dài hơn, nhiều hơn

Có sẵn từ Python 3.4, sử dụng đối tượng Path mới trong pathlib. Lưu ý rằng .exists không hoàn toàn đúng, vì các thư mục không phải là tệp (ngoại trừ theo nghĩa unix rằng mọi thứ là một tệp).

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

Vì vậy, chúng ta cần sử dụng is_file:

>>> root.is_file()
False

Đây là trợ giúp về is_file:

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

Vì vậy, hãy lấy một tệp mà chúng ta biết là một tệp:

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

Theo mặc định, NamedTemporaryFile xóa tệp khi đóng (và sẽ tự động đóng khi không còn tham chiếu nào nữa).

>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False

Tuy nhiên, nếu bạn đi sâu vào việc triển khai , bạn sẽ thấy rằng is_file sử dụng 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

Điều kiện cuộc đua: Tại sao chúng tôi thích thử

Chúng tôi thích try vì nó tránh được các điều kiện chủng tộc. Với try, bạn chỉ cần cố gắng đọc tệp của mình, hy vọng nó sẽ ở đó và nếu không, bạn sẽ bắt ngoại lệ và thực hiện bất kỳ hành vi dự phòng nào có ý nghĩa.

Nếu bạn muốn kiểm tra xem một tệp có tồn tại trước khi bạn cố đọc nó không, và bạn có thể đang xóa nó và sau đó bạn có thể đang sử dụng nhiều luồng hoặc quy trình, hoặc một chương trình khác biết về tệp đó và có thể xóa nó - bạn có nguy cơ a điều kiện cuộc đua nếu bạn kiểm tra nó tồn tại, bởi vì sau đó bạn đang racing để mở nó trước khi điều kiện (sự tồn tại của nó) thay đổi.

Điều kiện cuộc đua rất khó để gỡ lỗi vì có một cửa sổ rất nhỏ trong đó chúng có thể khiến chương trình của bạn bị lỗi.

Nhưng nếu đây là động lực của bạn, bạn có thể nhận giá trị của câu lệnh try bằng cách sử dụng trình quản lý bối cảnh suppress.

Tránh các điều kiện cuộc đua mà không có tuyên bố thử: suppress

Python 3.4 cung cấp cho chúng tôi suppress trình quản lý bối cảnh (trước đây là ignore trình quản lý bối cảnh), thực hiện chính xác về mặt ngữ nghĩa trong cùng một dòng, trong khi (ít nhất là bề ngoài) đáp ứng yêu cầu ban đầu để tránh try tuyên bố:

from contextlib import suppress
from pathlib import Path

Sử dụng:

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

Đối với các Pythons trước đó, bạn có thể cuộn suppress của riêng mình, nhưng không có try sẽ dài dòng hơn so với. Tôi tin đây thực sự là câu trả lời duy nhất không sử dụng try ở bất kỳ cấp độ nào trong Python có thể được áp dụng cho trước Python 3.4 vì nó sử dụng trình quản lý bối cảnh thay thế:

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)

Có lẽ dễ dàng hơn với một thử:

from contextlib import contextmanager

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

Các tùy chọn khác không đáp ứng yêu cầu "không thử":

isfile

import os
os.path.isfile(path)

từ tài liệu :

os.path.isfile(path)

Trả về True nếu đường dẫn là một tệp thông thường hiện có. Điều này tuân theo các liên kết tượng trưng, ​​vì vậy cả islink()isfile() đều có thể đúng cho cùng một đường dẫn.

Nhưng nếu bạn kiểm tra nguồn của chức năng này, bạn sẽ thấy nó thực sự sử dụng câu lệnh thử:

# 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

Tất cả những gì nó đang làm là sử dụng đường dẫn đã cho để xem liệu nó có thể lấy số liệu thống kê trên đó hay không, bắt OSError và sau đó kiểm tra xem đó có phải là tệp nếu nó không đưa ra ngoại lệ.

Nếu bạn có ý định làm một cái gì đó với tệp, tôi sẽ đề nghị trực tiếp thử nó với một lần thử - ngoại trừ để tránh điều kiện cuộc đua:

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

os.access

Có sẵn cho Unix và Windows là os.access, nhưng để sử dụng, bạn phải truyền cờ và nó không phân biệt giữa các tệp và thư mục. Điều này được sử dụng nhiều hơn để kiểm tra xem người dùng thực sự có quyền truy cập trong môi trường đặc quyền nâng cao hay không:

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

Nó cũng bị các vấn đề về điều kiện chủng tộc tương tự như isfile. Từ tài liệu :

Lưu ý: Sử dụng access () để kiểm tra xem người dùng có được phép sử dụng không, ví dụ: mở một tệp trước khi thực sự làm như vậy bằng cách sử dụng open () tạo ra lỗ hổng bảo mật, bởi vì người dùng có thể khai thác khoảng thời gian ngắn giữa việc kiểm tra và mở tệp để thao tác. Nó thích hợp sử dụng các kỹ thuật EAFP. Ví dụ:

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

được viết tốt hơn là:

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

Tránh sử dụng os.access. Đây là một hàm cấp thấp có nhiều cơ hội hơn cho lỗi người dùng so với các đối tượng và hàm cấp cao hơn được thảo luận ở trên.

Chỉ trích một câu trả lời khác:

Một câu trả lời khác nói điều này về os.access:

Cá nhân, tôi thích cái này vì dưới mui xe, nó gọi API gốc (thông qua "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), nhưng nó cũng mở ra một cổng cho các lỗi người dùng có thể xảy ra và nó không phải là Pythonic như các biến thể khác :

Câu trả lời này cho biết họ thích một phương pháp không có lỗi Pythonic, không có lỗi, không có lý do chính đáng. Dường như khuyến khích người dùng sử dụng API cấp thấp mà không hiểu chúng.

Nó cũng tạo ra một trình quản lý bối cảnh, bằng cách trả lại vô điều kiện True, cho phép tất cả các Ngoại lệ (bao gồm KeyboardInterruptSystemExit!) Vượt qua một cách im lặng, đó là một cách tốt để che giấu lỗi.

Điều này dường như để khuyến khích người dùng áp dụng các thực hành kém.

110
Aaron Hall
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!"

Nhập os giúp điều hướng và thực hiện các hành động tiêu chuẩn với hệ điều hành của bạn dễ dàng hơn.

Để tham khảo cũng xem Làm cách nào để kiểm tra xem một tệp có tồn tại bằng Python không?

Nếu bạn cần các hoạt động cấp cao, hãy sử dụng shutil.

82
bishop

Kiểm tra các tệp và thư mục bằng os.path.isfile(), os.path.isdir()os.path.exists()

Giả sử rằng "đường dẫn" là một đường dẫn hợp lệ, bảng này hiển thị những gì được trả về bởi mỗi chức năng cho các tệp và thư mục:

 enter image description here

Bạn cũng có thể kiểm tra xem một tệp có phải là một loại tệp nhất định hay không bằng cách sử dụng os.path.splitext() để nhận tiện ích mở rộng (nếu bạn chưa biết)

>>> 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
75
Tom Fuller

Trong năm 2016, cách tốt nhất vẫn là sử dụng os.path.isfile:

>>> os.path.isfile('/path/to/some/file.txt')

Hoặc trong Python 3, bạn có thể sử dụng pathlib:

import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
    ...
67
KaiBuxe

Dường như không có sự khác biệt về ý nghĩa chức năng giữa thử/ngoại trừ và isfile(), vì vậy bạn nên sử dụng cái nào có ý nghĩa.

Nếu bạn muốn đọc một tập tin, nếu nó tồn tại, hãy làm

try:
    f = open(filepath)
except IOError:
    print 'Oh dear.'

Nhưng nếu bạn chỉ muốn đổi tên một tệp nếu nó tồn tại và do đó không cần phải mở nó, hãy làm

if os.path.isfile(filepath):
    os.rename(filepath, filepath + '.old')

Nếu bạn muốn ghi vào một tập tin, nếu nó không tồn tại, hãy làm

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

Nếu bạn cần khóa tập tin, đó là một vấn đề khác.

62
chad

Bạn có thể thử điều này (an toàn hơn):

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

Thông số sẽ là:

([Errno 2] Không có tệp hoặc thư mục như vậy: 'anything.txt')

Sau đó, tùy thuộc vào kết quả, chương trình của bạn có thể tiếp tục chạy từ đó hoặc bạn có thể mã để dừng nó nếu bạn muốn.

53
philberndt

Mặc dù tôi luôn khuyên bạn nên sử dụng các câu lệnh tryexcept, đây là một vài khả năng dành cho bạn (sở thích cá nhân của tôi là sử dụng os.access):

  1. Hãy thử mở tệp:

    Mở tệp sẽ luôn xác minh sự tồn tại của tệp. Bạn có thể tạo một chức năng giống như vậy:

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

    Nếu nó sai, nó sẽ dừng thực thi với IOError hoặc OSError chưa được xử lý trong các phiên bản sau của Python. Để bắt ngoại lệ, bạn phải sử dụng mệnh đề thử ngoại trừ. Tất nhiên, bạn luôn có thể sử dụng câu lệnh try ngoại trừ như vậy (cảm ơn hsandt để khiến tôi suy nghĩ):

    def File_Existence(filepath):
        try:
            f = open(filepath)
        except IOError, OSError: # Note OSError is for later versions of Python
            return False
    
        return True
    
  2. Sử dụng os.path.exists(path):

    Điều này sẽ kiểm tra sự tồn tại của những gì bạn chỉ định. Tuy nhiên, nó kiểm tra các tập tinthư mục vì vậy hãy cẩn thận về cách bạn sử dụng nó.

    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
    
  3. Sử dụng os.access(path, mode):

    Điều này sẽ kiểm tra xem bạn có quyền truy cập vào tập tin. Nó sẽ kiểm tra quyền. Dựa trên tài liệu os.py, nhập os.F_OK, nó sẽ kiểm tra sự tồn tại của đường dẫn. Tuy nhiên, sử dụng điều này sẽ tạo ra một lỗ hổng bảo mật, vì ai đó có thể tấn công tệp của bạn bằng cách sử dụng thời gian giữa việc kiểm tra quyền và mở tệp. Thay vào đó, bạn nên trực tiếp mở tệp thay vì kiểm tra quyền của nó. ( EAFP vs LBYP ). Nếu bạn sẽ không mở tệp sau đó và chỉ kiểm tra sự tồn tại của nó, thì bạn có thể sử dụng tệp này.

    Dù sao, ở đây:

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

Tôi cũng nên đề cập rằng có hai cách mà bạn sẽ không thể xác minh sự tồn tại của một tệp. Vấn đề sẽ là permission denied hoặc no such file or directory. Nếu bạn bắt được IOError, hãy đặt IOError as e (như tùy chọn đầu tiên của tôi), sau đó nhập print(e.args) để bạn có thể xác định vấn đề của mình. Tôi hy vọng nó sẽ giúp! :)

48
Zizouz212

Ngày: 2017-12-04

Mỗi giải pháp có thể đã được liệt kê trong các câu trả lời khác.

Một cách trực quan và có thể tranh luận để kiểm tra xem một tập tin có tồn tại hay không là như sau:

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

Tôi đã thực hiện một chiếc áo choàng đầy đủ để bạn tham khảo:

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

Ngoài ra, os.access():

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

R_OK, W_OKX_OK các cờ để kiểm tra quyền ( doc ).

32
zgoda

Nếu tệp để mở, bạn có thể sử dụng một trong các kỹ thuật sau:

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

CẬP NHẬT

Chỉ để tránh nhầm lẫn và dựa trên các câu trả lời tôi nhận được, câu trả lời hiện tại tìm thấy một tệp hoặc một thư mục có tên đã cho.

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

Tăng các ngoại lệ được coi là một cách tiếp cận có thể chấp nhận và Pythonic, để kiểm soát dòng chảy trong chương trình của bạn. Xem xét xử lý các tệp bị thiếu với IOErrors. Trong tình huống này, một ngoại lệ IOError sẽ được nêu ra nếu tệp tồn tại nhưng người dùng không có quyền đọc.

SRC: http://www.pfinn.net/python-check-if-file-exists.html

20
Pedro Lobito

Bạn có thể viết đề xuất của Brian mà không cần try:.

from contextlib import suppress

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

suppress là một phần của Python 3.4. Trong các bản phát hành cũ hơn, bạn có thể nhanh chóng viết ra sự kìm nén của chính mình:

from contextlib import contextmanager

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

Nếu bạn đã nhập NumPy cho các mục đích khác thì không cần nhập thư viện khác như pathlib, os, paths, v.v.

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

Điều này sẽ trả về đúng hay sai dựa trên sự tồn tại của nó.

17
durjoy

Kiểm tra tập tin hoặc thư mục tồn tại

Bạn có thể làm theo ba cách sau:

Lưu ý1: os.path.isfile chỉ được sử dụng cho các tệp

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

Lưu ý2: os.path.exists được sử dụng cho cả tệp và thư mục

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

Phương thức pathlib.Path (có trong Python 3+, có thể cài đặt với pip cho Python 2)

from pathlib import Path
Path(filename).exists()
16
Ali Hallaji

Thêm một biến thể nhỏ nữa mà không được phản ánh chính xác trong các câu trả lời khác.

Điều này sẽ xử lý trường hợp file_pathNone hoặc chuỗi rỗng.

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

Thêm một biến thể dựa trên đề xuất từ ​​Shahbaz

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

Thêm một biến thể dựa trên đề xuất từ ​​Peter Wood

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

Tôi là tác giả của một gói đã tồn tại khoảng 10 năm và nó có chức năng giải quyết trực tiếp câu hỏi này. Về cơ bản, nếu bạn đang sử dụng hệ thống không phải Windows, nó sử dụng Popen để truy cập find. Tuy nhiên, nếu bạn đang ở trên Windows, nó sẽ sao chép find với một trình đi bộ hệ thống tập tin hiệu quả.

Bản thân mã không sử dụng khối try ngoại trừ trong việc xác định hệ điều hành và do đó hướng bạn đến kiểu "Unix" find hoặc hand-buillt find. Các thử nghiệm về thời gian cho thấy try nhanh hơn trong việc xác định HĐH, vì vậy tôi đã sử dụng một hệ thống ở đó (nhưng không ở đâu khác).

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

Và tài liệu

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

>>>

Việc triển khai, nếu bạn quan tâm, sẽ ở đây: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190

15
Mike McKerns

Đây là lệnh Python 1 dòng cho môi trường dòng lệnh Linux. Tôi thấy điều này RẤT TUYỆT VỜI vì tôi không phải là một anh chàng Bash nóng bỏng.

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

Tôi hy vọng điều này là hữu ích.

Làm cách nào để kiểm tra xem một tệp có tồn tại mà không sử dụng câu lệnh try không?

Trong năm 2016, đây vẫn là cách dễ nhất để kiểm tra xem cả hai tệp có tồn tại hay không và đó có phải là tệp không:

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

isfile thực sự chỉ là một phương thức trợ giúp sử dụng nội bộ os.statstat.S_ISREG(mode) bên dưới. os.stat này là một phương thức cấp thấp hơn sẽ cung cấp cho bạn thông tin chi tiết về các tệp, thư mục, ổ cắm, bộ đệm, v.v. Thông tin thêm về os.stat tại đây

Lưu ý: Tuy nhiên, cách tiếp cận này sẽ không khóa tệp theo bất kỳ cách nào và do đó mã của bạn có thể trở nên dễ bị " thời gian kiểm tra đến thời điểm sử dụng " (TOCTTOU) lỗi.

Vì vậy, nâng cao các ngoại lệ được coi là một cách tiếp cận có thể chấp nhận và Pythonic, để kiểm soát dòng chảy trong chương trình của bạn. Và người ta nên xem xét việc xử lý các tệp bị thiếu bằng IOErrors, thay vì các câu lệnh if (chỉ là một lời khuyên).

11
Inconnu

Bạn có thể sử dụng thư viện "HĐH" của Python:

>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
11
Pradip Das
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)
9
Khaled.K

Bạn có thể sử dụng phương pháp mở sau để kiểm tra xem một tệp có tồn tại + có thể đọc được không:

open(inputFile, 'r')
9
user3197473
import os
path = /path/to/dir

root,dirs,files = os.walk(path).next()
if myfile in files:
   print "yes it exists"

Điều này rất hữu ích khi kiểm tra một số tập tin. Hoặc bạn muốn thực hiện giao cắt/trừ với một danh sách hiện có.

8
Jesvin Jose

Để kiểm tra nếu một tập tin tồn tại,

from sys import argv

from os.path import exists
script, filename = argv
target = open(filename)
print "file exists: %r" % exists(filename)
7
Hanson

Bạn có thể sử dụng os.listdir để kiểm tra xem một tập tin có nằm trong một thư mục nhất định không.

import os
if 'file.ext' in os.listdir('dirpath'):
    #code
5
iPhynx
import os

# for testing purpose args defaulted to current folder & 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))

Về cơ bản kiểm tra thư mục, sau đó kiểm tra tệp bằng dấu tách thư mục thích hợp bằng cách sử dụng os.path.join .

4
Vimal Maheedharan

Bạn chắc chắn nên sử dụng cái này.

from os.path import exists

if exists("file") == True:
    print "File exists."
Elif exists("file") == False:
    print "File doesn't exist."
3
user2154354

Có lẽ không cần thiết nhưng nếu có, đây là một số mã

import os

def file_exists(path, filename):
    for file_or_folder in os.listdir(path):
        if file_or_folder == filename:
            return True
    return False
0