存在しない可能性のあるファイルを削除するためのほとんどのpythonicの方法


453

ファイルfilenameが存在する場合は削除したい。言うのは適切ですか

if os.path.exists(filename):
    os.remove(filename)

もっと良い方法はありますか?1行の方法ですか?


7
ファイルが存在する場合はファイルを削除してみて(権限がない場合は失敗して)、ベストエフォートの削除を実行して、エラーが発生しないようにしますか?
ドナルフェロー

@DonalFellowsの言った「前者」をやりたかった。そのため、私はスコットの元のコードが良いアプローチになると思いますか?
LarsH

関数を呼び出しunlinkて、名前空間PHPに配置します。
lama12345 2014年

1
@LarsH受け入れられた回答の2番目のコードブロックを参照してください。例外が「そのようなファイルまたはディレクトリではありません」エラー以外の場合は、例外を再生成します。
jpmc26 2014

回答:


613

よりpythonicな方法は次のようになります:

try:
    os.remove(filename)
except OSError:
    pass

これはさらに多くの行を取り、非常に見苦しく見えos.path.exists()ますが、例外を使いすぎるというPythonの規則への不必要な呼び出しを回避し、従います。

これを行う関数を書くのは価値があるかもしれません:

import os, errno

def silentremove(filename):
    try:
        os.remove(filename)
    except OSError as e: # this would be "except OSError, e:" before Python 2.6
        if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory
            raise # re-raise exception if a different error occurred

17
しかし、削除操作が失敗した場合、これは成功しますか(読み取り専用ファイルシステムまたはその他の予期しない問題)。
Scott C Wilson

135
また、os.path.exists()実行時にファイルが存在しても、実行時に存在するとは限りませんos.remove()
キンドール

8
私の+1ですが、例外の多用はPythonの規則ではありません:)それともそうですか?
2012年

8
@pepr私は、例外がPythonの通常の動作の一部であるかを滑稽に批判していました。たとえば、イテレータ、反復を停止するために例外を発生させる必要があります。
マット

5
+2できないから+1。よりPythonicであることに加えて、これは実際には正しいですが、オリジナルはそうではありません。このような
競合

159

TOCTTOUのバグを回避するために、ファイルの存在を確認するのではなく、例外を抑制する方を好みます。Mattの答えはこれの良い例ですが、Python 3では、次のようにして少し単純化できますcontextlib.suppress()

import contextlib

with contextlib.suppress(FileNotFoundError):
    os.remove(filename)

filenamepathlib.Path文字列ではなくオブジェクトの場合、を.unlink()使用する代わりにそのメソッドを呼び出すことができますos.remove()。私の経験では、Pathオブジェクトは、ファイルシステム操作では文字列よりも便利です。

この回答のすべてがPython 3専用であるため、アップグレードするもう1つの理由が提供されます。


7
これは、2015年12月の最もPython的な方法です。Pythonは進化し続けています。
Mayank Jaiswal

2
Python 3.6のpathlib.Pathオブジェクトのremove()メソッドが見つかりませんでした
BrianHVB

1
@jeffbyrnes:私はそれをPythonのZenの違反と呼びます:「それを行うための明白な方法は1つ、できれば1つだけあるべきです。」同じことをする2つのメソッドがある場合、ソースコードの実行中にそれらが混在することになり、読者が理解するのが難しくなります。私は、彼らがとの一貫性を望んでいたのでunlink(2)はないかと思います。
ケビン

1
@nivk:except句が必要な場合は、try/ を使用する必要がありますexcept。あなたが最初のブロック、ブロック自体、第二のブロックを導入するラインを導入するラインを持っている必要がありますので、それは意味のある、短くすることはできませんし、そのブロックは、それほどtry/ exceptできるだけ簡潔としてすでにあります。
ケビン

1
try / exceptブロックとは異なり、このソリューションでは、テストカバレッジメトリックが適切であることを確認するために例外を作成する必要がないことを意味します。
スクラーク

50

os.path.existsTrueファイルだけでなくフォルダも返します。os.path.isfile代わりにを使用して、ファイルが存在するかどうかを確認することを検討してください。


4
存在をテストし、そのテストに基づいて削除するときはいつでも、競合状態に自分を解放します。(ファイルが間に消えた場合はどうなりますか?)
Alex L

34

アンディ・ジョーンズの答えの精神で、本物の三項演算はどうですか?

os.remove(fn) if os.path.exists(fn) else None

41
三元の醜い誤用。
bgusach '10 / 09/15

19
@BrianHVB 3値は、分岐を行わずに、条件に基づいて2つの値から選択するためのものです。
bgusach 2016年

1
フロー制御に例外を使用したくありません。これらはコードを理解しにくくし、さらに重要なことに、発生する他のエラー(ファイルの削除をブロックするアクセス許可の問題など)をマスクして、サイレントエラーを発生させる可能性があります。
Ed King

11
これはアトミックではありません。ファイルは、existsとremoveの呼び出しの間に削除できます。操作を試みて失敗させる方が安全です。
ConnorWGarvey 2017

1
@ nam-g-vu参考までに、基本的に元の質問者の構文を代替として追加しただけなので、編集をロールバックしました。彼らはそれとは違う何かを探していたので、編集がこの特定の答えに密接に関連しているとは思いません。
Tim Keating

9

ファイルが存在するかどうかを確認して削除する別の方法は、モジュールglobを使用することです。

from glob import glob
import os

for filename in glob("*.csv"):
    os.remove(filename)

Globは、* nixワイルドカードを使用してパターンを選択できるすべてのファイルを検索し、リストをループします。


9

Python 3.8の時点でmissing_ok=Trueandを使用pathlib.Path.unlinkdocs here

from pathlib import Path

my_file = Path("./dir1/dir2/file.txt")

# Python 3.8+
my_file.unlink(missing_ok=True)

# Python 3.7 and earlier
if my_file.exists():
    my_file.unlink()

1
私の意見では、実用的なpython3に対する最良の回答です。
mrgnw


6
if os.path.exists(filename): os.remove(filename)

ワンライナーです。

多くの人が反対するかもしれません-多分「醜い」3項の使用を検討するような理由で-しかし、これは私たちが標準でない醜いものを呼ぶときに醜い標準に慣れている人々に耳を傾けるべきかどうかという疑問を投げかけます。


3
これは問題ありません-フロー制御に例外を使用したくありません。これらはコードを理解しにくくし、さらに重要なことに、発生する他のエラー(ファイルの削除をブロックするアクセス許可の問題など)をマスクして、サイレントフェイルを引き起こす可能性があります。
Ed King

2
ファイル名を変更するプロセスが1つしかないことを想定しているため、これはきれいではありません。それはアトミックではありません。操作を試みて正常に失敗するのは安全で正しいことです。Pythonが標準化できないのは不愉快です。ディレクトリがある場合は、shutilを使用すると、必要なものが正確にサポートされます。
ConnorWGarvey 2017


1

このようなもの?短絡評価を利用します。ファイルが存在しない場合、条件全体がtrueになることはないため、Pythonは2番目の部分の評価を気にしません。

os.path.exists("gogogo.php") and os.remove("gogogo.php")

25
これは明らかに「よりPython的」ではありません。実際、これはGuidoが特に警告するものであり、ブール演算子の「乱用」と呼ばれています。
abarnert 2012年

1
ああ、私は同意します-質問の一部は1行の方法を要求し、これは私の頭に浮かんだ最初の事柄でした
アンディジョーンズ

4
まあ、コロンの後ろの改行を削除するだけで、ワンライナーにすることもできます…または、さらに良いことに、Guideは不快にif式を追加して、「ブール演算子の誤用」を防ぎ、証明する絶好の機会があります何でも悪用される可能性がある:os.remove( "gogogo.php")if os.path.exists( "gogogo.php")elseなし。:)
abarnert

0

KISSオファリング:

def remove_if_exists(filename):
  if os.path.exists(filename):
    os.remove(filename)

その後:

remove_if_exists("my.file")

1
関数全体を記述しなければならない場合、それは一種のワンライナーのポイントを見逃しているようです
Ion Lesan

@Ion Lesan OPは、この問題を解決するための「最良の」方法の後にあります。読みやすさを損なう場合、ワンライナーは決して良い方法ではありません。
Baz

「最良」の本質的に広い定義を考えると、TOCTOUの影響を明確に受けていますが、私はこの意味で議論するつもりはありません。そして、間違いなくKISSソリューションではありません。
Ion Lesan

@Matt Trueですが、ここで提供されている多くのソリューションがこの問題の影響を受けていませんか?
Baz

0

これは別の解決策です:

if os.path.isfile(os.path.join(path, filename)):
    os.remove(os.path.join(path, filename))

0

独自のメッセージを例外とする別のソリューション。

import os

try:
    os.remove(filename)
except:
    print("Not able to delete the file %s" % filename)

-1

私はオプションとしてでrm存在しないファイルを強制的に削除できるを使用--preserve-rootしましたrm

--preserve-root
              do not remove `/' (default)

rm --help | grep "force"
  -f, --force           ignore nonexistent files and arguments, never prompt

safe-rmsudo apt-get install safe-rm)も使用できます

Safe-rmは、/ bin / rmをラッパーで置き換えることにより、重要なファイルが誤って削除されるのを防ぐことを目的とした安全ツールです。ラッパーは、削除すべきでないファイルとディレクトリの構成可能なブラックリストに対して特定の引数をチェックします。

まず、フォルダ/ファイルのパスが存在するかどうかを確認します。これにより、変数fileToRemove /folderToRemove to the string-r / `を設定できなくなります。


import os, subprocess

fileToRemove = '/home/user/fileName';
if os.path.isfile(fileToRemove):
   subprocess.run(['rm', '-f', '--preserve-root', fileToRemove]
   subprocess.run(['safe-rm', '-f', fileToRemove]

1
この些細なことのためにシェルを使用するのはやり過ぎであり、このアプローチはクロスプラットフォーム(つまりWindows)でも機能しません。
ナブラ

4
標準ライブラリ(たとえばos.remove)の代わりにシェルを使用することは、常に何かを行うための最もPythonic / cleanな方法の1つです。たとえば、シェルから返されたエラーを手動で処理する必要があります。
ナブラ

1
rm安全に使用し、防止するための回答を追加しましたrm -r /。@JonBrave
alper

1
rm -f --preserve-root十分ではありません(--preserve-rootとにかくおそらくデフォルトです)。私は-r / 例として挙げましたが、それが何かだったら-r /homeどうでしょうか?あなたはおそらく望んrm -f -- $fileToRemoveでいるが、それはポイントではありません。
JonBrave

3
変数名(環境変数)を使用した使用方法ではなく、引用符も保護もありません。そして、この質問ではありません。不注意にさらすことos.system('rm ...')は非常に危険です。
JonBrave
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.