5105

ファイルが書き込まれるディレクトリが存在するかどうかを確認し、存在しない場合はPythonを使用してディレクトリを作成する最もエレガントな方法は何ですか? これが私が試したものです:

import os

file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)

try:
    os.stat(directory)
except:
    os.mkdir(directory)

f = file(filename)

どういうわけか、私は見逃しましたos.path.exists(kanja、Blair、および Douglas に感謝します)。これは私が今持っているものです:

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

これを自動的に行うためのフラグはありopen()ますか?

4

29 に答える 29

6415

Python≥3.5では、以下を使用しますpathlib.Path.mkdir

from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)

古いバージョンのPythonの場合、質の良い2つの回答があり、それぞれに小さな欠陥があるので、それについて説明します。

試してみて、作成os.path.existsを検討os.makedirsしてください。

import os
if not os.path.exists(directory):
    os.makedirs(directory)

コメントや他の場所で指摘されているように、競合状態があります。ディレクトリがos.path.existsとの間に作成された場合、os.makedirsは。os.makedirsで失敗しますOSErrorOSError残念ながら、権限の不足やディスクのフルなどの他の要因によるディレクトリの作成の失敗を無視するため、包括的キャッチと継続は絶対確実ではありません。

1つのオプションは、埋め込まれたエラーコードをトラップしOSErrorて調べることです(PythonのOSErrorから情報を取得するクロスプラットフォームの方法はありますか?を参照)。

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

あるいは、2番目os.path.existsのが存在する可能性がありますが、別の人が最初のチェックの後にディレクトリを作成し、2番目のチェックの前にそれを削除したと仮定します。

アプリケーションによっては、同時操作の危険性は、ファイルのアクセス許可などの他の要因によってもたらされる危険性よりも多かれ少なかれ異なる場合があります。開発者は、実装を選択する前に、開発中の特定のアプリケーションとその予想される環境について詳しく知る必要があります。

FileExistsErrorPythonの最新バージョンは、 (3.3以降で)公開することにより、このコードをかなり改善しています...

try:
    os.makedirs("path/to/directory")
except FileExistsError:
    # directory already exists
    pass

...そしてキーワード引数がos.makedirs呼び出されるexist_okことを許可することによって(3.2以降)。

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.
于 2008-11-07T19:06:07.663 に答える
1428

Python 3.5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

pathlib.Path.mkdir上記で使用したように、再帰的にディレクトリを作成し、ディレクトリが既に存在する場合は例外を発生させません。親を作成する必要がない、または作成したくない場合は、parents引数をスキップしてください。

Python 3.2+:

使用pathlib:

可能であれば、pathlibという名前の現在のバックポートをインストールしますpathlib2。という名前の保守されていない古いバックポートをインストールしないでくださいpathlib。次に、上記の Python 3.5+ セクションを参照して、同じように使用します。

Python 3.4 を使用している場合、付属していますpathlibが、便利なexist_okオプションがありません。mkdirバックポートは、この不足しているオプションを含む、より新しく優れた実装を提供することを目的としています。

使用os:

import os
os.makedirs(path, exist_ok=True)

os.makedirs上記で使用したように、再帰的にディレクトリを作成し、ディレクトリが既に存在する場合は例外を発生させません。デフォルトexist_ok値がFalse. この引数は、Python 2.x から 2.7 までには存在しません。そのため、Python 2.7 のように手動で例外を処理する必要はありません。

Python 2.7+:

使用pathlib:

可能であれば、pathlibという名前の現在のバックポートをインストールしますpathlib2。という名前の保守されていない古いバックポートをインストールしないでくださいpathlib。次に、上記の Python 3.5+ セクションを参照して、同じように使用します。

使用os:

import os
try: 
    os.makedirs(path)
except OSError:
    if not os.path.isdir(path):
        raise

単純なソリューションでは、最初に を使用してから を使用する場合がありますos.path.isdiros.makedirs、上記のソリューションでは 2 つの操作の順序が逆になります。そうすることで、ディレクトリを作成する際の重複した試行に関係する一般的な競合状態を防ぎ、ディレクトリからファイルを明確にします。

例外をキャプチャして使用することは、ファイルとディレクトリの両方に対して、つまりが発生するerrnoため、有用性が限られていることに注意してください。ディレクトリが存在するかどうかを確認するだけの方が信頼性が高くなります。OSError: [Errno 17] File existserrno.EEXIST

別:

mkpathネストされたディレクトリを作成し、ディレクトリが既に存在する場合は何もしません。これは Python 2 と 3 の両方で機能します。

import distutils.dir_util
distutils.dir_util.mkpath(path)

バグ 10948によると、この代替手段の重大な制限は、指定されたパスの python プロセスごとに 1 回しか機能しないことです。つまり、それを使用してディレクトリを作成し、Python の内部または外部からディレクトリを削除mkpathし、同じディレクトリを再作成するために再度使用mkpathすると、以前にディレクトリを作成したという無効なキャッシュ情報が黙って使用され、実際にディレクトリを再作成します。対照的に、os.makedirsそのようなキャッシュに依存しません。この制限は、一部のアプリケーションでは問題ない場合があります。


ディレクトリのモードについては、気になる方はドキュメントを参照してください。

于 2013-01-16T17:31:19.700 に答える
643

try except と errno モジュールからの適切なエラー コードを使用すると、競合状態が解消され、クロスプラットフォームになります。

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

つまり、ディレクトリを作成しようとしますが、ディレクトリが既に存在する場合はエラーを無視します。一方、その他のエラーは報告されます。たとえば、事前にディレクトリ「a」を作成し、そこからすべての権限を削除すると、OSError(errno.EACCES権限が拒否されました、エラー 13) が発生します。

于 2011-02-17T17:17:25.517 に答える
123

Python 3.5 以降でpathlib.Path.mkdirは、次のexist_okフラグがあります。

from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True) 
# path.parent ~ os.path.dirname(path)

これにより、ディレクトリが再帰的に作成され、ディレクトリが既に存在する場合は例外が発生しません。

(python 3.2から始まるフラグをos.makedirs取得したのと同じように)exist_okos.makedirs(path, exist_ok=True)


注:私がこの回答を投稿したとき、言及された他の回答はありませんexist_ok...

于 2016-12-14T16:06:09.100 に答える
122

os.path.isdir()個人的には、 の代わりに testを使用することをお勧めしますos.path.exists()

>>> os.path.exists('/tmp/dirname')
True
>>> os.path.exists('/tmp/dirname/filename.etc')
True
>>> os.path.isdir('/tmp/dirname/filename.etc')
False
>>> os.path.isdir('/tmp/fakedirname')
False

あなたが持っている場合:

>>> dir = raw_input(":: ")

そして愚かなユーザー入力:

:: /tmp/dirname/filename.etc

...でテストすると、filename.etcその引数をに渡すときに名前が付けられたディレクトリになります。os.makedirs()os.path.exists()

于 2009-01-14T17:57:32.920 に答える
97

チェックos.makedirs:(完全なパスが存在することを確認します。)
ディレクトリが存在する可能性があるという事実を処理するには、をキャッチしOSErrorます。(exist_okFalse(デフォルト)のOSError場合、ターゲットディレクトリがすでに存在する場合はanが発生します。)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass
于 2008-11-07T19:01:25.677 に答える
63

os.path.exists機能を試す

if not os.path.exists(dir):
    os.mkdir(dir)
于 2008-11-07T19:00:01.717 に答える
41

私は以下を書き留めました。しかし、それは完全に絶対確実というわけではありません。

import os

dirname = 'create/me'

try:
    os.makedirs(dirname)
except OSError:
    if os.path.exists(dirname):
        # We are nearly safe
        pass
    else:
        # There was an error on creation, so make sure we know about it
        raise

私が言っているように、これは本当に絶対確実ではありません。ディレクトリの作成に失敗する可能性があり、その期間中に別のプロセスでディレクトリを作成する可能性があるからです。

于 2008-11-07T21:23:03.333 に答える
33

ディレクトリが存在するかどうかを確認し、必要に応じて作成しますか?

これに対する直接的な答えは、他のユーザーやプロセスがディレクトリをいじることがないと予想される単純な状況を想定すると、次のようになります。

if not os.path.exists(d):
    os.makedirs(d)

または、ディレクトリの作成が競合状態の対象となる場合 (つまり、パスが存在することを確認した後、何か他のものが既に作成されている可能性がある場合) は、次のようにします。

import errno
try:
    os.makedirs(d)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise

しかし、おそらくさらに良いアプローチは、次の方法で一時ディレクトリを使用して、リソースの競合の問題を回避することですtempfile

import tempfile

d = tempfile.mkdtemp()

オンラインドキュメントの要点は次のとおりです。

mkdtemp(suffix='', prefix='tmp', dir=None)
    User-callable function to create and return a unique temporary
    directory.  The return value is the pathname of the directory.

    The directory is readable, writable, and searchable only by the
    creating user.

    Caller is responsible for deleting the directory when done with it.

Python 3.5 の新機能pathlib.Path:exist_ok

Pathパスで使用したい多くのメソッドを持つ新しいオブジェクト (3.4 時点) があります。そのうちの 1 つはmkdir.

(文脈上、私はスクリプトを使用して毎週の担当者を追跡しています。これは、同じデータに対して 1 日に複数回 Stack Overflow にアクセスすることを回避できるスクリプトのコードの関連部分です。)

最初に関連するインポート:

from pathlib import Path
import tempfile

今は対処する必要はありませんos.path.join- パス部分を : で結合するだけ/です:

directory = Path(tempfile.gettempdir()) / 'sodata'

次に、ディレクトリが存在することをべき等的に確認します -exist_ok引数は Python 3.5 で表示されます:

directory.mkdir(exist_ok=True)

ドキュメントの関連部分は次のとおりです。

exist_oktrue の場合、例外FileExistsErrorは無視されますが (コマンドと同じ動作POSIX mkdir -p)、最後のパス コンポーネントが既存の非ディレクトリ ファイルでない場合のみです。

ここにもう少しスクリプトがあります-私の場合、私は競合状態の影響を受けません.ディレクトリ(または含まれるファイル)がそこにあることを期待するプロセスは1つしかなく、削除しようとするものは何もありません.ディレクトリ。

todays_file = directory / str(datetime.datetime.utcnow().date())
if todays_file.exists():
    logger.info("todays_file exists: " + str(todays_file))
    df = pd.read_json(str(todays_file))

Pathパスstrを期待する他のA​​PI がそれらを使用できるようになる前に、オブジェクトを強制する必要があります。str

おそらく、抽象基本クラスのインスタンスを受け入れるように Pandas を更新する必要がありますos.PathLike

于 2015-01-22T23:45:59.470 に答える
26

Python 3.4 では、新しいpathlibモジュールも使用できます。

from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
    if not path.parent.exists():
        path.parent.mkdir(parents=True)
except OSError:
    # handle error; you can also catch specific errors like
    # FileExistsError and so on.
于 2015-03-11T20:50:01.437 に答える
25

ワンライナー ソリューションの場合は、次を使用できますIPython.utils.path.ensure_dir_exists()

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

ドキュメントから:ディレクトリが存在することを確認します。存在しない場合は、作成して、別のプロセスが同じことをしている場合に競合状態から保護してください。

IPython は拡張パッケージであり、標準ライブラリの一部ではありません。

于 2016-03-29T15:50:53.783 に答える
21

Python3では、os.makedirs設定をサポートしますexist_ok。デフォルト設定は です。これは、ターゲット ディレクトリが既に存在する場合に発生することFalseを意味します。OSErrorに設定exist_okするとTrueOSError(ディレクトリが存在する) は無視され、ディレクトリは作成されません。

os.makedirs(path,exist_ok=True)

Python2では、os.makedirs設定をサポートしていませんexist_okheikki-toivonen's answer のアプローチを使用できます。

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise
于 2017-01-03T22:33:47.480 に答える
19

関連する Python ドキュメントでは、 EAFP コーディング スタイル (許可よりも許しを求める方が簡単)の使用が提案されています。これは、コードが

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

代替案よりも優れている

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

この質問で説明されている競合状態のため、ドキュメントはこれを正確に示唆しています。さらに、他の人がここで言及しているように、OS に対して 2 回ではなく 1 回クエリを実行すると、パフォーマンスが向上します。最後に、場合によっては (開発者がアプリケーションが実行されている環境を知っている場合)、2 番目のコードを支持する可能性があるという主張は、プログラムが専用環境をセットアップしたという特別な場合にのみ提唱できます。それ自体 (および同じプログラムの他のインスタンス)。

その場合でも、これは悪い習慣であり、役に立たない長いデバッグにつながる可能性があります。たとえば、ディレクトリのアクセス許可を設定したからといって、アクセス許可が目的に応じて適切に設定されているという印象を与えるべきではありません。親ディレクトリは、他の権限でマウントできます。一般に、プログラムは常に正しく動作する必要があり、プログラマーは 1 つの特定の環境を期待するべきではありません。

于 2014-07-14T15:29:07.270 に答える
10

Heikki ToivonenABBの回答を見て、このバリエーションについて考えました。

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST or not os.path.isdir(path):
            raise
于 2016-02-08T04:08:06.240 に答える
8

これに使用できますos.listdir

import os
if 'dirName' in os.listdir('parentFolderPath')
    print('Directory Exists')
于 2016-06-08T12:52:46.870 に答える
1

Pythonでこれを行う最良の方法

#Devil
import os
directory = "./out_dir/subdir1/subdir2"
if not os.path.exists(directory):
    os.makedirs(directory)
于 2022-02-08T06:11:08.027 に答える