例外なくファイルが存在するかどうかを確認するにはどうすればよいですか?


回答:


5153

チェックしている理由がのようなことができるようif file_exists: open_it()にする場合は、tryaround を使用して開こうとするほうが安全です。チェックしてから開くと、ファイルを削除または移動したり、チェックしてから開こうとしたりする間にリスクが生じます。

ファイルをすぐに開く予定がない場合は、 os.path.isfile

Trueパスが既存の通常のファイルである場合に返します。これはシンボリックリンクをたどるので、同じパスに対してislink()isfile()の両方をtrueにすることができます。

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

40
最初の備考(開く前にチェックする場合は「試してみる」を使用)について残念ながら、追加するために開く場合は、存在するかどうかを確認するため、存在しない場合は 'a'モードが作成されるため、これは機能しません。
makapuf

6
FileNotFoundErrorあなたはまた、Pythonの2.7と同様にPythonの3をサポートする必要がある場合はPython 3で導入されましたが、あなたが使用することができますIOError(代わりにFileNotFoundErrorサブクラス)stackoverflow.com/a/21368457/1960959
scottclowe

7
@makapufこれを開いて「更新」(open('file', 'r+'))し、最後まで検索できます。
キリル

2111

あなたはos.path.exists機能を持っています:

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

これはTrueファイルとディレクトリの両方に戻りますが、代わりに使用できます

os.path.isfile(file_path)

具体的にはファイルかどうかをテストします。シンボリックリンクに従います。


966

とは異なり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


320

使用する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")

60
複数の条件があり、そのうちのいくつかは不必要であることが、明確で明確ではありません
2013

10
また、冗長です。ファイルが存在しない場合は、os.access()falseを返します。
ローン侯爵

9
@EJP Linuxでは、ファイルは存在できますがアクセスできません。
e-info128 2018

8
import osあなたはimport os.pathそれがすでにの一部であるので、あなたは再びする必要はありませんos。あなただけの輸入に必要なos.pathだけの機能を使用しようとしている場合os.pathからではなくos小さい事をインポートするには、それ自身が、あなたが使用してos.accessos.R_OK、第二のインポートは必要ありません。
Jester

287
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

2
一般に、変数にメソッド名と同じ名前を付けることはお勧めしません。
Homunculus Reticulli

245

ほとんどすべての可能な方法が既存の回答(少なくとも1つ)にリストされていますが(たとえば、Python 3.4固有のものが追加されました)、すべてを一緒にグループ化するようにします。

:これから投稿するすべてのPython標準ライブラリコードは、バージョン3.5.3に属しています。

問題の説明

  1. ファイル(引数:フォルダー(「特別」ファイル)も)の存在を確認する
  2. try / except / else / finallyブロック使用しないでください

可能な解決策

  1. [Python 3]:os.path。存在するパス(またのような他の機能ファミリーのメンバーを確認しos.path.isfileos.path.isdiros.path.lexistsわずかに異なる行動のために)

    os.path.exists(path)

    パスが既存のパスまたは開いているファイル記述子を参照しているTrueかどうか返します。False壊れたシンボリックリンクを返します。一部のプラットフォームでFalseは、パスが物理的に存在していても、要求されたファイルに対してos.stat()を実行する権限が付与されていない場合、この関数が返されることがあります。

    すべて順調ですが、インポートツリーに従っている場合:

    • 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

    それだけだ試し / 除き、周りのブロック[Pythonの3]:OS。statpath、*、dir_fd = None、follow_symlinks = True。したがって、コードはtry / free を除いてですが、フレームスタックの下には(少なくとも)そのようなブロックが1つあります。これは他の関数(を含む os.path.isfile)にも適用されます。

    1.1。[Python 3]:パス。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 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 - 例外を選択的に抑制するために特別に設計されました


    しかし、[Python 3]のように、それらはtry / except / else / 最終的にブロックするラッパーのようですwithステートメントは次のように述べています:

    これにより、共通の試み ... を除いて ... 最終的に使用パターンをカプセル化して、簡単に再利用できます。

  3. ファイルシステムトラバーサル関数(および一致するアイテムの結果を検索)


    彼らは我々の問題のために非効率的である(ほとんどの場合)フォルダの上にこれらの反復、以来(非ワイルドカードのような例外があるグロブ私はそれらを主張するつもりはないので、 - @ShadowRangerが指摘したようにビンビン)。言うまでもなく、ファイル名の処理が必要になる場合もあります。

  4. [Python 3]:os。accesspath、mode、*、dir_fd = None、effective_ids = False、follow_symlinks = True)に近い動作os.path.exists(実際には、主に2 番目の引数により広い)

    • ドキュメントに記載されているように、ユーザーのアクセス許可により、ファイルの「表示」が制限される場合があります。

      ...呼び出し元のユーザーがパスへの指定されたアクセス権を持っているかどうかをテストします。パスの存在をテストするには、モードF_OKにする必要があります...

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

    私はまた、作業のでCボンネットの下に、それが呼び出すので、私もこの方法を使用して、ネイティブAPI S(経由再び、「$ {PYTHON_SRC_DIR} /Modules/posixmodule.cを」)、それはまた、可能するためのゲートを開き、ユーザエラー、それは他のバリアントほどPython icではありません。したがって、@ AaronHallが正しく指摘したように、何をしているのかわからない場合は使用しないでください。

    :ネイティブAPIの呼び出しは、[Python 3]: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(にもかかわらず、ユニコードそれらの間の関連の違い)
    • これは非常に特定の領域を対象としていますが、これまでの回答には記載されていませんでした


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

    • 代わりにlibcのパス("/lib/x86_64-linux-gnu/libc.so.6")をハードコーディングします。これは、システム間で異なる可能性があり(ほとんどの場合)、なし(または空の文字列)をCDLLコンストラクターに渡すことができます。(ctypes.CDLL(None).access(b"/tmp", os.F_OK))。[man7]によると:DLOPEN(3)

      filenameがNULLの場合、返されるハンドルはメインプログラム用です。このハンドルをdlsym()に指定すると、メインプログラム内のシンボルが検索され、プログラムの起動時に読み込まれるすべての共有オブジェクトが続き、フラグRTLD_GLOBALを指定してdlopen()によって読み込まれるすべての共有オブジェクトが続きます。

      • メイン(現在の)プログラム(python)はlibcに対してリンクされているため、そのシンボル(accessを含む)がロードされます
      • mainPy_Mainなど(すべて)のよう関数が利用できるため、これは注意して処理する必要があります。それらを呼び出すと、(現在のプログラムに)悲惨な影響を与える可能性があります
      • これはWinにも当てはまりません(ただし、msvcrt.dllはデフォルトで%PATH%にある"%SystemRoot%\ System32"にあるため、それほど大きな問題ではありません)。私は物事をさらに進め、Winでこの動作を再現したいと思います(そしてパッチを送信します)が、結局のところ[MS.Docs]:GetProcAddress関数エクスポートされたシンボルを「見る」だけなので、誰かがメイン実行可能ファイルで関数を宣言しない限り(地球上の理由正規の人はそれを行うのでしょうか?)は、メインプログラムは、ロード可能なもののほとんど使用できません__declspec(dllexport)
  5. ファイルシステム機能を備えたサードパーティのモジュールをインストールする

    ほとんどの場合、上記の方法のいずれかに依存します(わずかなカスタマイズが必要な場合があります)。
    一例は次のようになり(再び、勝利特定)[GitHubの]:mhammond / pywin32 -パイソンのWindows(pywin32)拡張のためであり、PythonのオーバーラッパーWINAPI S。

    しかし、これは回避策のようなものなので、ここで停止します。

  6. 別の(不完全な)回避策(gainarie)は(私がそれを呼んでみたい)sysadminアプローチです:Pythonをラッパーとして使用してシェルコマンドを実行します

    • 勝つ

      (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
    • NixLnxUbtu)):

      [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

結論

  • やるの使用を試して / 除く外 / / 最後に、彼らはあなたが厄介な一連の問題に実行して防ぐことができるので、ブロックを。私が考えることができる反例はパフォーマンスです:そのようなブロックはコストがかかるので、毎秒数十万回実行されることになっているコードに配置しないようにしてください(ただし、(ほとんどの場合)ディスクアクセスが含まれるため、そうではありません)。

最後のメモ

  • 私はそれを最新に保つように努めます、どんな提案も歓迎します、私は答えに出てくるであろう有用なものを組み込みます

3
このステートメントについて詳しく説明していただけますか?「それは良い習慣ではありませんが、呼び出しでos.F_OKを使用していますが、これは明確にするためです(その値は0です)」
sk8asd123 '19

6
@ sk8asd123:コメントでそれを行うのは難しいです:一般的に、一緒に来る関数で定数を使用するのが最善です。これは、同じ定数を定義する複数のモジュールを操作するときに適用されます。これは、一部のモジュールが最新ではない可能性があるためです。関数と定数を同期させることをお勧めします。ctypesを操作するとき(関数を直接呼び出す)、定数を定義する必要があります(MSDNから)、または定数をまったく使用しないでください。これは私が使用するガイドラインにすぎません。99.9%では、(機能的に)おそらく違いはありません。
CristiFati 2017年

3
@CristiFati:3.6以降glob.iglob(およびglob.glob同様)はに基づいているos.scandirため、現在は面倒です。10Mファイルのディレクトリで最初のヒットを取得するには、最初のヒットに到達するまでスキャンするだけです。3.6より前でもglob、ワイルドカードなしのメソッドを使用する場合、関数はスマートです。ヒットが1つだけであることがわかっているため、グロブ処理が単純にos.path.isdirまたはos.path.lexists(パスがで終わるかどうかに応じて)単純化さ/ます。
ShadowRanger 2017年

3
私のコメントのその2番目の部分(ワイルドカード化されていないグロビングは、実際にはフォルダーを反復処理せず、決して行わない)は、それが問題を完全に効率的に解決することを意味します(直接呼び出すよりも遅いos.path.isdiros.path.lexist、Pythonレベルの関数呼び出しと文字列の束であるため)効率的なパスを決定する前の操作は実行可能ですが、追加のシステムコールやI / O作業はありません。
ShadowRanger 2017年

154

これは、ファイルが存在するかどうかを確認する最も簡単な方法です。ちょうどので、あなたがチェックすると、ファイルが存在しない保証あなたがそれを開くために必要がある場合、それはあるだろうということ。

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

17
ファイルにアクセスするつもりであれば、プログラムの構築方法に関係なく、競合状態は存在します。プログラムは、コンピューター上の別のプロセスがファイルを変更していないことを保証できません。これは、エリックリッペルトが外因性の例外と呼んでいるものです。事前にファイルの存在を確認しても避けられません。
Isaac Supeene 2014年

@IsaacSupeeneベストプラクティスは、(ファイル)操作のウィンドウをできるだけ小さくして、適切な例外処理を行うことです
un33k

145

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

124

tryステートメントを優先します。それはより良いスタイルと見なされ、競合状態を回避します。

それを私の言葉にしないでください。この理論には多くの支持があります。ここにいくつかあります:


3
ステートメントをサポートするために、より適切なソースを追加してください。
BlueTrin

11
引用された競合状態の回避(apple dev support)リンクはあなたの答えをサポートしていません。制限された権限を介して一時ファイル/ディレクトリを適切にサンドボックス化しない、適切に設計されていないオペレーティングシステムでの機密情報を含む一時ファイルの使用のみに関係します。とにかく使用try...exceptしてもその問題の解決には役立ちません。
jstine 2015

この方法の問題は、存在しないファイルに依存する重要なコードがある場合、それをexcept:節に入れると、コードのこの部分で発生した例外によって混乱するメッセージが表示されることです(2番目のエラーは最初のものの処理)。
カミオン

119

Pythonを使用して、tryステートメントを使用せずにファイルが存在するかどうかを確認するにはどうすればよいですか?

Python 3.4以降で利用可能になりPath、ファイル名を指定してオブジェクトをインポートしてインスタンス化し、is_fileメソッドを確認します(これにより、通常のファイルを指すシンボリックリンクに対してもTrueが返されることに注意してください)。

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

あなたは、Python 2を使っているのであれば、あなたは、は、PyPIからpathlibモジュールをバックポートすることができpathlib2、またはそれ以外のチェックisfileからos.pathモジュール:

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

さて、上記はおそらくここで最も実用的な直接的な答えですが、競合状態の可能性があります(達成しようとしていることに依存します)。また、基礎となる実装はを使用しますがtry、Pythonはtryその実装のあらゆる場所で使用します。

Pythonはtryどこでも使用するため、それを使用する実装を回避する理由は本当にありません。

しかし、この回答の残りの部分では、これらの警告を検討しようとしています。

より長く、より知識豊富な答え

Python 3.4以降で使用可能です。新しいPathオブジェクトをで使用してくださいpathlib。注.existsディレクトリが(というUNIXの意味を除いてファイルではないので、非常に適切ではありませんすべてがファイルです)。

>>> 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すると、ファイルがあることを期待してファイルを読み取ろうとし、そうでない場合は例外をキャッチして、意味のあるフォールバック動作を実行します。

読み取る前にファイルが存在することを確認したい場合、そのファイルを削除して、複数のスレッドまたはプロセスを使用している可能性があります。または、別のプログラムがそのファイルを認識しており、削除できる可能性があります。あなたがそれがレースしているので、あなたがそれが存在することを確認するならば、レース状態の前にそれを開くための条件(その存在)の変更。

非常に小さなウィンドウがあり、プログラムが失敗する可能性があるため、競合状態のデバッグは非常に困難です。

しかし、これがあなたの動機である場合、次のコマンドを使用してステートメントの値を取得できます。trysuppressコンテキストマネージャ。

tryステートメントなしで競合状態を回避する: suppress

Python 3.4は、suppressコンテキストマネージャー(以前のignoreコンテキストマネージャー)を提供します。これは、意味的にまったく同じことを少ない行で実行すると同時に、(少なくとも表面的には)元の要求を満たし、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では、独自のをロールすることができましたsuppressが、a tryを使用しない場合よりも詳細になります。これは実際には、try Python 3.4以前のバージョンに適用できるPythonのどのレベルでも使用さない唯一の回答であると確信しています。これは、代わりにコンテキストマネージャを使用しているためです。

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

「試さずに」の要求に応えない他のオプション:

isfile

import os
os.path.isfile(path)

ドキュメントから:

os.path.isfile(path)

パスが既存の通常のファイルである場合は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-exceptで直接試すことをお勧めします。

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

os.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ではありません。 :

この答えは、正当性のない、Python以外のエラーが発生しやすい方法を好むと述べています。低レベルAPIを理解せずに使用することをユーザーに奨励しているようです。

また、無条件にを返すTrueことにより、すべての例外(KeyboardInterruptおよびSystemExit!を含む)が暗黙的に渡されるようにするコンテキストマネージャも作成します。これは、バグを非表示にするための優れた方法です。

これは、ユーザーに不適切な慣行を採用するように促すようです。


87
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すると、オペレーティングシステムでの移動や標準アクションの実行が容易になります。

参照については、Pythonを使用してファイルが存在するかどうかを確認する方法も参照してください。

高レベルの操作が必要な場合は、を使用してくださいshutil


9
この答えは間違っています。os.path.existsディレクトリなど、ファイルではないものに対してtrueを返します。これにより、誤検知が発生します。推奨する他の回答を参照してくださいos.path.isfile
クリスジョンソン

84

で、ファイルやフォルダのためのテストos.path.isfile()os.path.isdir()およびos.path.exists()

「パス」が有効なパスであると仮定すると、次の表は、ファイルとフォルダの各関数によって返されるものを示しています。

ここに画像の説明を入力してください

ファイルが特定のタイプのファイルであるかどうかをテスト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

72

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

3
このチェックにpython3のモジュール「os」の代わりにモジュール「pathlib」を使用する利点は何ですか?
Joko、2016

3
pathlibパスのためのpythonのOOPソリューションです。あなたはそれでもっとたくさんのことができます。存在を確認する必要があるだけの場合、利点はそれほど大きくありません。
KaiBuxe 2016

65

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'

ファイルのロックが必要な場合、それは別の問題です。


3
この答えは間違っています。os.path.existsディレクトリなど、ファイルではないものに対してtrueを返します。これにより、誤検知が発生します。推奨する他の回答を参照してくださいos.path.isfile
クリスジョンソン

6
3番目の例でfilepathは、適切なタイミングで名前が付けられたリンクを作成し、BAMはターゲットファイルを上書きします。この問題を回避するにopen(filepath, 'wx')は、try...exceptブロックで行う必要があります。
2015

1
2番目の例では、少なくともWindowsで、すでに存在するOSError場合filepath + '.old'、「Windowsでは、dstがすでに存在する場合、ファイルであってもOSErrorが発生します。dst時にアトミックな名前変更を実装する方法がない場合があります。既存のファイルに名前を付けます。」
トムMyddeltyn

@TomMyddeltyn:Python 3.3以降、os.replace移植可能に宛先ファイルのサイレント置換を実行します(これはのos.renameLinuxの動作と同じです)(宛先名が存在し、ディレクトリである場合にのみエラーになります)。したがって、2.xで立ち往生していますが、Py3ユーザーは数年前から優れた選択肢を持っています。
ShadowRanger 2017年

rename例では、それはtry/ で実行する必要がありますexceptos.rename(またはos.replace最新のPythonでは)アトミックです。チェックして名前を変更すると、不要な競合と追加のシステムコールが発生します。ただやるtry: os.replace(filepath, filepath + '.old') except OSError: pass
ShadowRanger 2017年

59

あなたはこれを試すことができます(より安全):

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

その後、結果に応じて、プログラムはそこから実行を続けるか、必要に応じてプログラムを停止するようにコーディングできます。


18
元の質問は、使用しない解決策を求めていましたtry
rrs

5
この答えはOPの要点を逃しています。ファイルが存在するかどうかの確認は、ファイルを開くことができるかどうかの確認とは異なります。ファイルが存在する場合もありますが、さまざまな理由で開くことができません。
クリスジョンソン

51

私は常にtryand exceptステートメントの使用をお勧めしますが、ここにいくつかの可能性があります(私の個人的なお気に入りはを使用していますos.access)。

  1. ファイルを開いてみてください。

    ファイルを開くと、常にファイルの存在が確認されます。次のように関数を作成できます。

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

    Falseの場合、それ以降のバージョンのPythonでは、手に渡らないIOErrorまたはOSErrorで実行が停止します。例外をキャッチするには、try except節を使用する必要があります。もちろん、次のtryようにいつでもexcept`ステートメントを使用できます( 私に考えさせてくれたhsandtに感謝します)。

    def File_Existence(filepath):
        try:
            f = open(filepath)
        except IOError, OSError: # Note OSError is for later versions of Python
            return False
    
        return True
  2. 使用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
  3. 使用os.access(path, mode)

    これにより、ファイルにアクセスできるかどうかが確認されます。権限をチェックします。os.pyのドキュメントに基づいて、と入力os.F_OKすると、パスの存在が確認されます。ただし、権限を確認してからファイルを開くまでの時間を利用して誰かがファイルを攻撃する可能性があるため、これを使用するとセキュリティホールが発生します。代わりに、ファイルのアクセス許可を確認する代わりに、直接ファイルを開く必要があります。(EAFP vs LBYP)。後でファイルを開かず、その存在を確認するだけの場合は、これを使用できます。

    とにかく、ここ:

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

また、ファイルの存在を確認できない2つの方法があることにも触れておきます。問題はpermission deniedまたはno such file or directoryです。をキャッチした場合はIOErrorIOError as e(最初のオプションと同様に)を設定し、入力しprint(e.args)て問題を特定できるようにします。お役に立てば幸いです。:)


51

日付:2017-12-04

可能な解決策はすべて他の回答にリストされています。

ファイルが存在するかどうかを確認するための直感的で議論の余地のない方法は次のとおりです。

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

私はあなたの参照のために徹底的なチートシートを作りました:

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

37

ファイルを開く場合は、次のいずれかの方法を使用できます。

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

更新

混乱を避けるために、そして私が得た答えに基づいて、現在の答えは指定された名前のファイルまたはディレクトリを見つけます。


9
この答えは間違っています。os.path.existsディレクトリなど、ファイルではないものに対してtrueを返します。これにより、誤検知が発生します。推奨する他の回答を参照してくださいos.path.isfile
クリスジョンソン

誤検知の問題も発生しました。
Zorglub29、18年

docs.python.org/3/library/os.path.html#os.path.exists chrisからの上記のステートメントへ >> os.path.exists(path)>パスが既存のパスまたは開いているパスを参照している場合はTrueを返すファイル記述子。壊れたシンボリックリンクに対してFalseを返します。一部のプラットフォームでは、パスが物理的に存在していても、要求されたファイルに対してos.stat()を実行する権限が付与されていない場合、この関数はFalseを返すことがあります。バージョン3.3で変更:パスを整数にできるようになりました:開いているファイル記述子の場合はTrueを、それ以外の場合はFalseを返します。バージョン3.6で変更:パスのようなオブジェクトを受け入れます。
JayRizzo

36

さらに、os.access()

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

であることR_OKW_OKおよびX_OKアクセス権をテストするためのフラグ(doc)。


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

例外を発生させることは、プログラムでフロー制御を行うための受け入れ可能なPythonicのアプローチと見なされます。不足しているファイルをIOErrorsで処理することを検討してください。この状況では、ファイルは存在するがユーザーに読み取り権限がない場合、IOError例外が発生します。

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


3
OPは、ファイルが存在するかどうかを確認する方法を尋ねました。ファイルが存在することは可能ですが、ファイルを開くことができません。したがって、ファイルが存在するかどうかを確認するためのプロキシとしてファイルを開くことは正しくありません。誤ったネガティブになります。
クリスジョンソン

19

あなたが他の目的のために既にnumpyのをインポートした場合、その後のような他のライブラリをインポートする必要はありませんpathlibospathsなどは、

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

これは、その存在に基づいてtrueまたはfalseを返します。


18

なしでブライアンの提案を書くことができますtry:

from contextlib import suppress

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

suppressPython 3.4の一部です。古いリリースでは、独自の抑制をすばやく作成できます。

from contextlib import contextmanager

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

17

私は約10年間使用されているパッケージの作成者で、この質問に直接対処する機能があります。基本的に、Windows以外のシステムを使用Popenしている場合は、を使用してアクセスしますfind。ただし、Windowsを使用している場合はfind、効率的なファイルシステムウォーカーで複製されます。

コード自体はtryブロックを使用しません...オペレーティングシステムを決定することを除いて、したがって、「Unix」スタイルfindまたは手作りのにユーザーを誘導しfindます。タイミングテストの結果try、OSを決定する方が速いことがわかったので、そこで使用しました(他の場所では使用しませんでした)。

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


17

ファイルまたはディレクトリが存在することを確認してください

次の3つの方法があります。

注1:os.path.isfileファイルにのみ使用

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

注2:os.path.existsファイルとディレクトリの両方に使用

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

pathlib.Path方法(Pythonで含ま3+、Pythonの2ピップとインストール)

from pathlib import Path
Path(filename).exists()

16

他の回答に正確に反映されていないもう1つのわずかなバリエーションを追加します。

これは、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):

3
if (x) return true; else return false;本当にだけreturn xです。最後の4行はになることがありreturn os.path.isfile(file_path)ます。ここでは、関数全体をのように簡略化できますreturn file_path and os.path.isfile(file_path)
Shahbaz 2017年

return xの場合は注意が必要ですif (x)。Pythonは空の文字列をFalseと見なします。この場合、ブールではなく空の文字列が返されます。この関数の目的は、常にboolを返すことです。
マルセルウィルソン

1
本当です。しかし、この場合は、xあるos.path.isfile(..)ことがすでにBOOLですので。
Shahbaz 2017年

os.path.isfile(None)例外が発生するため、ifチェックを追加しました。おそらく代わりにtry / exceptでラップすることもできますが、この方法の方がより明示的だと感じました。
マルセルウィルソン

3
return file_path and os.path.isfile(file_path)
Peter Wood

15

Linuxコマンドライン環境用の1行のPythonコマンドを次に示します。私はそんなにホットなバッシュの男ではないので、私はこれは非常に便利です。

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

これがお役に立てば幸いです。


6
bash:の1行のチェック[ -f "${file}" ] && echo "file found" || echo "file not found"(これはと同じですif [ ... ]; then ...; else ...; fi)。
flotzilla、2015年

12

Pythonの「OS」ライブラリを使用できます。

>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False

5
この答えは間違っています。os.path.existsディレクトリなど、ファイルではないものに対してtrueを返します。これにより、誤検知が発生します。推奨する他の回答を参照してくださいos.path.isfile
クリスジョンソン

@Chris Johnson、os.path.exists()関数は、システムにパスが存在するかどうかをチェックします。PATHはDIRECTORYまたはFILEです。どちらの場合も問題なく動作します。いくつかの例をお試しください
Pradip Das

したがって、この答えは機能します。すごい。IFFパスファイルのことではありません。それが問題でしたか?No.
Debosmit Ray 2016

場合によります。「ファイル」の存在を判断する目的がパスがすでに存在するかどうかを確認することである場合(したがって、他の情報を削除せずに新しいデータを保存できるパスではない場合)は問題ありませんexists。おそらく既存のファイルを開いても安全かどうかを判断することが目的である場合、批判は正当化され、存在することは十分正確ではありません。悲しいことに、OPはどちらが望ましい目標であるかを指定していません(おそらく、今後はそうしません)。
starturtle

12

tryステートメントを使用せずに、ファイルが存在するかどうかを確認するにはどうすればよいですか?

2016年にも、これは間違いなく、ファイルが存在するかどうか、およびファイルであるかどうかを確認する最も簡単な方法です。

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

isfile実際には、内部で使用されるヘルパーメソッドでos.statあり、stat.S_ISREG(mode)その下にあります。これos.statは、ファイル、ディレクトリ、ソケット、バッファなどに関する詳細情報を提供する下位レベルの方法です。os.statの詳細はこちら

注:ただし、この方法ではファイルがロックされないため、コードが「チェックの時間から使用の時間」(TOCTTOU)のバグに対して脆弱になる可能性があります。

したがって、例外を発生させることは、プログラムでフロー制御を行うための受け入れ可能なPythonicのアプローチと見なされます。また、ifステートメントではなく、IOErrorsを使用して欠落ファイルを処理することを検討する必要があります(単なるアドバイス)。


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

@ j6m8はい、ファイルがprocess \ program \ threadによって到達可能で読み取り可能な場合isReadableFile(path,fileName)に返さTrueれます
Khaled.K
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.