質問:
ファイルが書き込まれるディレクトリが存在するかどうかを調べて、もし存在しない場合は、Pythonを使ってディレクトリを作るための最もエレガントな方法って何?
以下は試したんだけど:
|
どういうわけかos.path.existsっていうのがあるのを知らなかったので、こうしたんだけど:
|
これが自動的に行われるようにするような、 “open”のためのフラグってある?
回答1:
2つ答えがあって、それぞれに良し悪しがあるんだけど、僕が書くなら:
os.path.existsを試してみて、ディレクトリを作るにはos.makedirsはどうかな。
|
でもこれってちょっとややこしいんだ — もしディレクトリが os.path.existsとos.makedirs呼び出しの間に作られたら、os.makedirsはOSErrorで失敗する。残念だけど、助けを出すOSErrorとそれを実行し続けることはフールプルーフ(foolproof)じゃない。なぜなら、例えばアクセス許可がない場合とかディスク容量が無いとかの他の要因でディレクトリ作成が失敗してもそれを無視するからね。
1つのオプションは OSErrorをトラップし、埋め込まれたエラーコードを調べること。(PythonのOSErrorから情報を取得するためのクロスプラットフォームの方法はありますか?参照):
|
あるいは、2つ目の os.path.existsっていうのも考えられるけど、仮に別の人が一つ目のチェックの後にディレクトリを作って、2つ目のチェックの前に削除してしまう、みたいな場合でもうまくいかない可能性がある。
アプリケーションによって、同時操作の危険性はファイルアクセス権とかの他の要因によって引き起こされる危険性よりも高かったり低かったり刷るから、開発者は実装を選ぶ前に開発されてる特定のアプリケーションと期待されてる環境の詳細をよく知ってる必要があるよね。
回答2:
try exceptとerrnoモジュールの正しいエラーコードを使えば、競合状態(race condition)の可能性を排除できるし、クロスプラットフォームでもあるよ:
|
つまり、ディレクトリを作成しようとしますが、すでに存在する場合はエラーを無視する。一方、その他のエラーは報告される。
たとえば、’a’というディレクトリをあらかじめ作成しておき、その中からすべての権限を削除すると、errno.EACCESでOSErrorが発生するよ(パーミッションが拒否されました。エラー13)。
回答3:
私は個人的にはos.path.exists()よりも os.path.isdir()を使うのをおすすめするかな:
|
これがあるとして、
|
そして、こんなバカみたいなユーザー入力があると:
|
もしos.path.exists()でテストした場合、引数がos.makedirs()に渡されるから、filename.etcという名前のディレクトリができてしまうことになる。