ファイルが書き込まれるディレクトリが存在するかどうかを確認し、存在しない場合は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"のフラグがありますか?
質の良い2つの答えがあり、それぞれに小さな欠陥があります。そのため、私はそれについて考えます。
os.path.exists
を試してみて、 os.makedirs
を考えてみてください。
import os
if not os.path.exists(directory):
os.makedirs(directory)
コメントなどで述べたように、競合条件があります - ディレクトリがos.path.exists
とos.makedirs
の呼び出しの間に作成された場合、os.makedirs
はOSError
で失敗します。残念ながら、OSError
を包括的にとらえ続けて継続することは、パーミッション不足、フルディスクなどの他の要因によるディレクトリ作成の失敗を無視するため、絶対確実というわけではありません。
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番目のチェックの前にそのディレクトリが削除されたとします。
アプリケーションによっては、並行操作の危険性が、ファイル許可などの他の要因によってもたらされる危険性よりも多い場合も少ない場合もあります。開発者は、実装を選択する前に、開発中の特定のアプリケーションとその予想される環境についてさらに知る必要があります。
最近のバージョンのPythonでは、 FileExistsError
(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.
import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True)
pathlib.Path.mkdir
上記のように再帰的にディレクトリを作成し、そのディレクトリがすでに存在する場合は例外を発生させません。親を作成する必要がない場合、または作成する必要がない場合は、parents
引数をスキップしてください。
pathlib
を使用する:
可能であれば、 pathlib2
という名前の現在のpathlib
バックポートをインストールします。 pathlib
という名前の古い保守されていないバックポートをインストールしないでください。次に、上記のPython 3.5以降のセクションを参照して、同じように使用してください。
Python 3.4を使用している場合、たとえpathlib
が付いていても、便利なexist_ok
オプションが欠けています。バックポートは、この欠けているオプションを含むmkdir
のより新しく優れた実装を提供することを目的としています。
os
を使用する:
import os
os.makedirs(path, exist_ok=True)
os.makedirs
上記のように再帰的にディレクトリを作成し、そのディレクトリがすでに存在する場合は例外を発生させません。 Python 3.2+を使用している場合にのみオプションのexist_ok
引数があり、デフォルト値はFalse
です。この引数はPython 2.xから2.7までには存在しません。そのため、Python 2.7のように手動で例外を処理する必要はありません。
pathlib
を使用する:
可能であれば、 pathlib2
という名前の現在のpathlib
バックポートをインストールします。 pathlib
という名前の古い保守されていないバックポートをインストールしないでください。次に、上記のPython 3.5以降のセクションを参照して、同じように使用してください。
os
を使用する:
import os
try:
os.makedirs(path)
except OSError:
if not os.path.isdir(path):
raise
単純な解決法では最初に os.path.isdir
に続けて os.makedirs
を使用することができますが、上記の解決法では2つの操作の順序が逆になります。そうすることで、それは一般的な競合状態がディレクトリを作成しようとする重複した試みと関係があることを防ぎ、またディレクトリからのファイルを明確にします。
OSError: [Errno 17] File exists
、すなわちerrno.EEXIST
はファイルとディレクトリの両方に対して発生するので、例外を捕捉してerrno
を使用することは、有用性が限られていることに注意してください。単にディレクトリが存在するかどうかを確認する方が信頼性が高いです。
mkpath
はネストしたディレクトリを作成し、そのディレクトリがすでに存在する場合は何もしません。これはPython 2と3の両方で動作します。
import distutils.dir_util
distutils.dir_util.mkpath(path)
Per バグ10948 、この選択肢の深刻な制限は、与えられたパスに対してpythonプロセスごとに一度だけ動作することです。言い換えれば、それを使ってディレクトリを作成してから、そのディレクトリをPythonの内側または外側から削除し、もう一度mkpath
を使って同じディレクトリを再作成すると、mkpath
は単に以前にディレクトリを作成したという無効なキャッシュ情報を使用します。実際には再びディレクトリを作成することはありません。対照的に、os.makedirs
はそのようなキャッシュに依存しません。この制限はアプリケーションによっては問題ないかもしれません。
ディレクトリのmodeに関しては、気にしているのならドキュメントを参照してください。
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
言い換えれば、我々はディレクトリを作成しようとします、しかし、それらがすでに存在するならば、我々はエラーを無視します。一方、他のエラーは報告されます。たとえば、dir 'a'を事前に作成し、そこからすべての許可を削除すると、errno.EACCES
でOSError
が発生します(Permission denied、エラー13)。
個人的にはos.path.isdir()
の代わりに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
... os.makedirs()
でテストした場合、その引数をos.path.exists()
に渡すと、filename.etc
という名前のディレクトリになります。
os.makedirs :をチェックします(完全なパスが存在することを確認します)。
ディレクトリが存在する可能性があることを処理するために、OSErrorをキャッチします(exist_okがFalse(デフォルト)の場合、ターゲットディレクトリが既に存在する場合はOSErrorが送出されます)
import os
try:
os.makedirs('./path/to/somewhere')
except OSError:
pass
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)
これは再帰的にディレクトリを作成し、ディレクトリがすでに存在する場合は例外を発生させません。
(ちょうど os.makedirs
がpython 3.2から始まるexist_ok
フラグを取得したのと同じです。例えばos.makedirs(path, exist_ok=True)
)
特定のファイルを特定のパスに配置し、そのファイルパスからディレクトリを取り出します。次に、ディレクトリがあることを確認した後、ファイルを読み取り用に開こうとします。このコードについてコメントするには:
filename = "/my/directory/filename.txt" dir = os.path.dirname(filename)
組み込み関数dir
を上書きしないようにします。また、filepath
またはおそらくfullfilepath
はおそらくfilename
よりも優れたセマンティック名です。
import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)
あなたの最終的な目標は、このファイルを書くことで開くことです、あなたは最初に、記述のために述べています、しかし、あなたは本質的にこのようにreadingのためにファイルを開く、
if not os.path.exists(directory): os.makedirs(directory) f = file(filename)
なぜあなたはそこにいて読むことができると期待するファイルのためのディレクトリを作るのでしょうか?
ファイルを開こうとするだけです。
with open(filepath) as my_file:
do_stuff(my_file)
ディレクトリまたはファイルが存在しない場合は、関連するエラー番号を含むIOError
が表示されます。プラットフォームに関係なく、errno.ENOENT
は正しいエラー番号を指します。あなたが望むなら、あなたはそれをキャッチすることができます、例えば:
import errno
try:
with open(filepath) as my_file:
do_stuff(my_file)
except IOError as error:
if error.errno == errno.ENOENT:
print 'ignoring error because directory or file is not there'
else:
raise
これは おそらく あなたが欲しいものです。
この場合、おそらく競合状況に直面していません。なので、ちょうどあなたがしたようにしてください、しかし書くことのために、あなたはw
モード(または追加するためにa
)で開く必要があることに注意してください。ファイルを開くためにコンテキストマネージャを使用することもPythonのベストプラクティスです。
import os
if not os.path.exists(directory):
os.makedirs(directory)
with open(filepath, 'w') as my_file:
do_stuff(my_file)
しかし、すべてのデータを同じディレクトリに配置しようとするいくつかのPythonプロセスがあるとします。それから、ディレクトリの作成について競合があるかもしれません。その場合はmakedirs
呼び出しをtry-exceptブロックでラップするのが最善です。
import os
import errno
if not os.path.exists(directory):
try:
os.makedirs(directory)
except OSError as error:
if error.errno != errno.EEXIST:
raise
with open(filepath, 'w') as my_file:
do_stuff(my_file)
os.path.exists
関数を試してください。
if not os.path.exists(dir):
os.mkdir(dir)
私は次のことを書き留めました。それは完全に絶対確実というわけではありません。
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
私が言うように、これは本当に絶対確実というわけではありません。なぜなら、ディレクトリを作成できない可能性と、その間に別のプロセスがディレクトリを作成する可能性があるからです。
ディレクトリが存在するかどうかを確認し、必要に応じて作成しますか?
これに対する直接的な答えは、他のユーザやプロセスがあなたのディレクトリをめちゃくちゃにすることを期待していない単純な状況を想定していることです。
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.
pathlib.Path
とexist_ok
パスで使用したいと思う多くのメソッドを持つ新しいPath
オブジェクト(3.4現在)があります - そのうちの1つはmkdir
です。
(コンテキストとして、私はスクリプトで私の毎週の担当者を追跡しています。これは、同じデータに対して1日に1回以上スタックオーバーフローが発生するのを避けるためのスクリプトの関連部分です。)
まず関連する輸入品:
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_ok
がtrueの場合、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
パスを必要とする他のAPIがそれらを使用できるようにするには、str
オブジェクトをstr
に強制変換する必要があります。
おそらくPandasは抽象基底クラスos.PathLike
のインスタンスを受け入れるように更新されるべきです。
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.
関連する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番目のコードに有利になるという主張が提唱されるのは、プログラムがプライベート環境を設定したという特別な場合だけです。それ自体(および同じプログラムの他のインスタンス)。
その場合でも、これは悪い習慣であり、長く役に立たないデバッグにつながる可能性があります。たとえば、ディレクトリのアクセス許可を設定したという事実が、インプレッションのアクセス許可を持っていてはいけません。目的に合わせて適切に設定します。親ディレクトリは他の権限でマウントされる可能性があります。一般に、プログラムは常に正しく機能し、プログラマーは特定の環境を期待するべきではありません。
Python3 では、os.makedirs
はexist_ok
の設定をサポートします。デフォルト設定はFalse
です。これは、ターゲットディレクトリがすでに存在する場合はOSError
が発生することを意味します。 exist_ok
をTrue
に設定すると、OSError
(directory exists)は無視され、ディレクトリは作成されません。
os.makedirs(path,exist_ok=True)
Python2 では、os.makedirs
はexist_ok
の設定をサポートしていません。 heikki-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
mkpath
を使用できます
# Create a directory and any missing ancestor directories.
# If the directory already exists, do nothing.
from distutils.dir_util import mkpath
mkpath("test")
先祖ディレクトリも作成されることに注意してください。
Python 2と3で動作します。
私はos.path.exists()
を使用します、 here はディレクトリが存在するかどうかをチェックし、存在しない場合は作成し、存在する場合は削除するために使用できるPython 3スクリプトです(必要に応じて).
ユーザーにディレクトリの入力を促し、簡単に変更できます。
ワンライナーソリューションの場合は、IPython.utils.path.ensure_dir_exists()
を使用できます。
from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)
のドキュメントから : ディレクトリが存在することを確認してください。それが存在しない場合は、それを作成し、他のプロセスが同じことをしている場合は競合状態から保護するようにしてください。
Heikki Toivonen そして A-B-B の答えを見て、この変化について考えました。
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
ファイルI/Oを扱うときに考慮すべき重要なことは
そのため、if
でチェックして、後で読み書きすると、未処理のI/O例外が発生する可能性があります。それを行うための最善の方法は次のとおりです。
try:
os.makedirs(dir_path)
except OSError as e:
if e.errno != errno.EEXIS:
raise
これにはos.listdir
を使用できます。
import os
if 'dirName' in os.listdir('parentFolderPath')
print('Directory Exists')
私はこのQ/Aを見つけました、そして、私は最初私が得ていた失敗とエラーのいくつかに困惑しました。私はPython 3(Arch Linux x86_64システム上のAnaconda仮想環境のv.3.5)で働いています。
このディレクトリ構造を考慮してください。
└── output/ ## dir
├── corpus ## file
├── corpus2/ ## dir
└── subdir/ ## dir
これが私の実験やメモです。
# ----------------------------------------------------------------------------
# [1] https://stackoverflow.com/questions/273192/how-can-i-create-a-directory-if-it-does-not-exist
import pathlib
""" Notes:
1. Include a trailing slash at the end of the directory path
("Method 1," below).
2. If a subdirectory in your intended path matches an existing file
with same name, you will get the following error:
"NotADirectoryError: [Errno 20] Not a directory:" ...
"""
# Uncomment and try each of these "out_dir" paths, singly:
# ----------------------------------------------------------------------------
# METHOD 1:
# Re-running does not overwrite existing directories and files; no errors.
# out_dir = 'output/corpus3' ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/' ## works
# out_dir = 'output/corpus3/doc1' ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/doc1/' ## works
# out_dir = 'output/corpus3/doc1/doc.txt' ## no error but no file created (os.makedirs creates dir, not files! ;-)
# out_dir = 'output/corpus2/tfidf/' ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/' ## works
# out_dir = 'output/corpus3/a/b/c/d/' ## works
# [2] https://docs.python.org/3/library/os.html#os.makedirs
# Uncomment these to run "Method 1":
#directory = os.path.dirname(out_dir)
#os.makedirs(directory, mode=0o777, exist_ok=True)
# ----------------------------------------------------------------------------
# METHOD 2:
# Re-running does not overwrite existing directories and files; no errors.
# out_dir = 'output/corpus3' ## works
# out_dir = 'output/corpus3/' ## works
# out_dir = 'output/corpus3/doc1' ## works
# out_dir = 'output/corpus3/doc1/' ## works
# out_dir = 'output/corpus3/doc1/doc.txt' ## no error but creates a .../doc.txt./ dir
# out_dir = 'output/corpus2/tfidf/' ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/' ## works
# out_dir = 'output/corpus3/a/b/c/d/' ## works
# Uncomment these to run "Method 2":
#import os, errno
#try:
# os.makedirs(out_dir)
#except OSError as e:
# if e.errno != errno.EEXIST:
# raise
# ----------------------------------------------------------------------------
結論:私の意見では、「方法2」のほうが堅牢です。
次のことを考慮してください。
os.path.isdir('/tmp/dirname')
ディレクトリ(パス)が存在し、かつディレクトリであることを意味します。だから私にとっては、このようにして私が必要とすることができます。だから私はそれがフォルダ(ファイルではない)であり、存在することを確認することができます。
Pathlibライブラリを使用する
import pathlib
mypath="/my/directory"
pathlib.Path(mypath).mkdir(parents=True, exist_ok=True)
プログラム/プロジェクトの入り口で関数create_dir()
を呼び出します。
import os
def create_dir(directory):
if not os.path.exists(directory):
print('Creating Directory '+directory)
os.makedirs(directory)
create_dir('Project directory')
このコマンドcheckを使用してdirを作成します
if not os.path.isdir(test_img_dir):
os.mkdir(str("./"+test_img_dir))
ディレクトリを作成する前にフルパスを設定する必要があります。
import os,sys,inspect
import pathlib
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_folder = currentdir + "/" + "your_folder"
if not os.path.exists(your_folder):
pathlib.Path(your_folder).mkdir(parents=True, exist_ok=True)
これは私のために機能し、うまくいけば、それはあなたのためにも機能します
import os
if os.path.isfile(filename):
print "file exists"
else:
"Your code here"
あなたのコードがここにあるところでは(touch)コマンドを使用します
これは、ファイルが存在しているかどうかを確認し、存在していない場合は作成します。
シェル言語をサポートするマシン上で実行している場合、サブプロセスモジュールを使用しないのはなぜですか? python 2.7およびpython 3.6で動作します
from subprocess import call
call(['mkdir', '-p', 'path1/path2/path3'])
ほとんどのシステムでトリックをするべきです。