[python] 예외없이 파일이 존재하는지 어떻게 확인합니까?

try명령문 을 사용하지 않고 파일이 존재하는지 여부를 어떻게 확인 합니까?



답변

당신이 확인하는 이유가 당신과 같은 것을 할 수 있다면 if file_exists: open_it()그것을 try여는 시도 주위 를 사용하는 것이 더 안전 합니다. 확인 후 파일을 열면 파일이 삭제되거나 이동 될 때 또는 파일을 열 때와 열 때 사이에 무언가 위험이 있습니다.

파일을 즉시 열지 않을 경우 사용할 수 있습니다 os.path.isfile

True경로가 기존 일반 파일 인 경우 반환 합니다. 이는 심볼릭 링크를 따르므로 동일한 경로에 대해 islink ()isfile () 이 모두 참일 수 있습니다.

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

파일인지 확인해야하는 경우

Python 3.4부터 pathlib모듈 은 객체 지향 접근 방식을 제공합니다 ( pathlib2Python 2.7에서 백 포트 됨 ).

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


답변

당신은 os.path.exists기능이 있습니다 :

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

이것은 True파일과 디렉토리 모두에 대해 반환 하지만 대신 사용할 수 있습니다

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

if os.path.isfile(filepath):


답변

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


답변

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에 속합니다 .

문제 진술 :

  1. 파일 점검 ( 논쟁의 여지 : 폴더 ( “특별한”파일)?) 존재
  2. try / except / else / finally 블록을 사용하지 마십시오

가능한 해결책 :

  1. [파이썬 3] : os.path. 존재 ( 경로 ) (또한 같은 다른 기능 가족 구성원을 확인 os.path.isfile, os.path.isdir, os.path.lexists약간 다른 행동에 대한)

    os.path.exists(path)

    path 가 기존 경로 또는 열린 파일 설명자를 참조 True하면 반환 합니다 . 깨진 심볼릭 링크를 반환 합니다. 일부 플랫폼에서이 함수는 경로가 실제로 존재 하더라도 요청 된 파일에서 os.stat () 를 실행할 수 있는 권한이 부여되지 않은 경우 반환 될 수 있습니다.FalseFalse

    모두 좋지만 가져 오기 트리를 따르는 경우 :

    • os.pathposixpath.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 3] : os 주변 의 시도 / 제외 블록 입니다. stat ( path, *, dir_fd = None, follow_symlinks = True ) . 따라서 코드는 무료 / 시도를 제외하고 시도 하지만 프레임 스택에는 (적어도) 그러한 블록이 하나 이상 있습니다. 이는 다른 기능 (을 포함한 os.path.isfile ) 에도 적용됩니다 .

    1.1. [파이썬 3] : 경로. is_file ()

    • 경로를 다루는 더 환상적인 (그리고 더 많은 파이썬 ic) 방법 이지만
    • 후드에서 정확히 똑같은 일을합니다 ( pathlib.py , line ~ # 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 3] : 명령문 컨텍스트 관리자 사용 . 어느 한 쪽:

    • 하나를 만듭니다 :

      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 ...)
      • 그리고 사용법-나는 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 )예외 를 선택적으로 억제하기 위해 특별히 고안되었습니다.

    그러나, 그들은 이상 래퍼 것으로 보인다 시도 / 제외 / 다른 / 마지막 블록으로 [파이썬 3] : 사진 상태 :

    이것은 일반적인 수 있습니다 시도제외마지막으로 편리하게 재사용을 위해 캡슐화하는 사용 패턴을.

  3. 파일 시스템 탐색 기능 (및 일치하는 항목에 대한 결과 검색)

    그들은 우리의 문제에 대한 비효율적이다 (대부분의 경우) 폴더를 통해 이러한 반복 할 때문에 (비 와일드 카드 같은 예외가 있습니다 글로브의 내가 그들 주장하지 않을거야, 그래서 – @ShadowRanger는 지적 빙). 경우에 따라 파일 이름 처리가 필요할 수 있습니다.

  4. [파이썬 3] : os. access ( path, mode, *, dir_fd = None, effective_ids = False, follow_symlinks = True ) 동작이 가까운 os.path.exists(실제로는 주로 두 번째 인수 때문에 더 넓 습니다 )

    • doc 상태에 따라 사용자 권한으로 파일 “visibility”가 제한 될 수 있습니다.

      … 호출 사용자에게 지정된 path 액세스 권한이 있는지 테스트하십시오 . 경로가 있는지 테스트하려면 modeF_OK 여야합니다 .

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

    나는 또한 작업 때문에 C , 후드, 그것을 호출하기 때문에 나뿐만 아니라이 방법을 사용하는 네이티브 API (통해, 다시 “$ {PYTHON_SRC_DIR} /Modules/posixmodule.c” )뿐만 아니라 수에 대한 게이트 열립니다 사용자 errors 이며 다른 변형 만큼 Python ic 이 아닙니다 . 따라서 @AaronHall이 올바르게 지적했듯이 수행중인 작업을 모르는 경우 사용하지 마십시오.

    참고 : [Python 3]을 통해 네이티브 API를 호출 할 수도 있습니다 . 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 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

    참고 사항 :

    • 좋은 습관 os.F_OK은 아니지만 전화에 사용하고 있지만 명확성을 위해 사용됩니다 (값은 0 )
    • 내가 사용하고 _waccess을 에 동일한 코드가 작동하도록 Python3Python2 (에도 불구하고 유니 코드가 그들 사이의 차이를 관련)
    • 이것은 매우 구체적인 영역을 목표로하지만 이전 답변에서는 언급되지 않았습니다.

    LNX ( Ubtu (16 64) 뿐만 아니라) 상대 :

    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

    참고 사항 :

    • 대신 시스템에 따라 다를 수있는 libc 의 경로 ( “/lib/x86_64-linux-gnu/libc.so.6” )를 하드 코딩하는 대신 CDLL 생성자에 None (또는 빈 문자열)을 전달할 수 있습니다. ( ). [man7] 에 따르면 : DLOPEN (3) :ctypes.CDLL(None).access(b"/tmp", os.F_OK)

      경우 파일 이름이 NULL이고, 다음 반환 된 핸들은 메인 프로그램입니다. dlsym ()이 주어지면 이 핸들은 기본 프로그램에서 기호를 찾은 다음 프로그램 시작시로드 된 모든 공유 객체 와 RTDL_GLOBAL 플래그 로 dlopen ()에 의해로드 된 모든 공유 객체 를 검색합니다 .

      • 메인 (현재) 프로그램 ( python )은 libc에 연결되어 있으므로 심볼 ( 액세스 포함 ) 이로 드됩니다
      • main , Py_Main 및 기타 기능과 같은 기능을 사용할 수 있으므로주의해서 다루어야 합니다. 그것들을 호출하면 비참한 영향을 줄 수 있습니다 (현재 프로그램에서)
      • 이것은 또한 적용되지 않습니다 (하지만 이후 즉, 같은 큰 문제가 아니다 MSVCRT.DLL가 에 위치한 “% SYSTEMROOT % \ SYSTEM32”% 경로 % 기본적으로). 더 나아가서 Win 에서이 동작을 복제 하고 패치를 제출하고 싶었지만 , [MS.Docs] : GetProcAddress 함수내 보낸 심볼 만 “보여” , 누군가가 주 실행 파일에서 함수를 선언하지 않는 한 로 __declspec(dllexport)(지구에있는 이유는 일반 사람이 그렇게 할 것?)는 메인 프로그램은로드 할 수 있지만, 거의 사용할 수 없습니다
  5. 파일 시스템 기능이있는 일부 타사 모듈 설치

    대부분 위의 방법 중 하나에 의존 할 것입니다 (약간의 사용자 정의가있을 수 있음).
    하나의 예는 (다시 Win에 따라) [GitHub] : mhammond / pywin32-Windows 용 Python (pywin32) ExtensionsWINAPIPython 래퍼 입니다.

    그러나 이것은 해결 방법과 비슷하기 때문에 여기서 멈 춥니 다.

  6. 또 다른 (불충분 한) 해결 방법 ( gainarie )은 sysadmin 접근 방식입니다 ( 파이썬 을 래퍼로 사용하여 쉘 명령 실행)

    • 승리 :

      (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
    • 닉스 ( 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 "import os; print(os.system('ls \"/tmp.notexist\" > /dev/null 2>&1'))"
      512

결론 :

  • 수행 사용 시도 / 제외시켰다 / 다른 / 마침내 그들은 당신이 불쾌한 일련의 문제로 실행되지 않도록 할 수 있기 때문에, 블록. 제가 생각할 수있는 반례는 성능입니다. 이러한 블록은 비용이 많이 들기 때문에 초당 수십만 번 실행되도록 코드에 배치하지 마십시오 (그러나 대부분의 경우 디스크 액세스가 필요합니다. 그렇지 않습니다).

최종 메모 :

  • 나는 그것을 최신 상태로 유지하려고 노력할 것입니다, 어떤 제안이라도 환영합니다, 나는 대답에 올 수있는 유용한 것을 통합 할 것입니다