2013-01-29 15 views
20

ファイルが存在するかどうかを判断する際に、tryステートメントを使用して "競合状態"を回避する方法はありますか?tryステートメントを使用して競合状態を回避するにはどうすればよいですか?

answer(更新:削除されました)は、os.path.exists()を使用すると、それ以外の場合は存在しない機会が生じることを暗示しているようです。

与えられた例は次のとおりです。

try: 
    with open(filename): pass 
except IOError: 
    print 'Oh dear.' 

しかし、私はそれがに比べて競合状態を避ける方法を理解していないよ:

攻撃者がして何かをすることができ os.path.exists(filename)を呼び出すどのよう
if not os.path.exists(filename): 
    print 'Oh dear.' 

彼らがまだできなかったファイル?

答えて

24

競合状態がありますもちろん、あなたのプログラムとファイル上で動作する他のコードとの間(競合条件は常に少なくとも2つの並列プロセスまたはスレッドを必要とします、詳しくはthisを参照してください)。それは、open()代わりのexists()を使用すると、実際には2つの状況で役立つことを意味します

  1. Webサーバー内で実行する場合は、その多くの場合、しかし、(いくつかのバックグラウンド・プロセスによって作成されたか、削除されたファイルの存在を確認しますつまり、HTTPリクエストを処理するために並行して実行されているプロセスのコピーがたくさんあるため、他のプログラムがない場合でも競合状態が発生する可能性があります。
  2. 存在すると思われる瞬間にファイルを破棄してコードをクラッシュさせようとしている悪質なプログラムが実行されている可能性があります。

exists()ただ1回チェックします。ファイルが存在する場合、exists()の後にマイクロ秒で削除され、Trueが返されます。ファイルが存在しない場合は、すぐに作成されることがあります。

しかし、ファイルの存在をテストするだけでなく、ファイルを開きます通常、ファイルは誰かが開いている間は削除できません。つまり、内部がwithであることを完全に確信している可能性があります。ファイルは開いているので、実際に存在しています。 withの中にしか当てはまりませんが、ブロックが終了するとすぐにファイルが削除されることがありますが、ファイルが存在する必要があるコードをwithに置くと、コードが失敗しないことが保証されます。

9

は、ここでの使用例です:

try: 
    with open('filename') as f: 
     do_stuff_that_depends_on_the_existence_of_the_file(f) 
except IOError as e: 
    print 'Trouble opening file' 

あなたはまったくアクセスしてファイルを開いている場合は、OSは、ファイルが存在することを保証する、またはそうでなければエラーで失敗します。アクセスが排他的である場合、ファイルの競合する他のプロセスは、あなたによってブロックされるか、ブロックされます。

tryは、PythonのファイルI/O APIが通常はリターンコードを持たないため(例外が代わりに使用されるため)、ファイルを開く行為のエラーまたは成功を検出する方法です。あなたの質問に本当に答えるためには、競合状態を避けるのはtryではありません。それはopenです。これは基本的にC(Pythonのベース)と同じですが、例外はありません。詳細についてはthisをお読みください。

tryブロック内のファイルへのアクセスに依存するコードを実行することをお勧めします。ファイルを閉じると、その存在はもはや保証されません。

os.path.existsを呼び出すと、ファイルが存在する場合と存在しない場合があり、ファイルの存在を知らない時点でスナップショットが表示されるだけです。os.path.existsが返されます。悪意のあるコードや予期しないロジックは、期待していないときにファイルを削除または変更する可能性があります。運転する前に道路がはっきりしていることを確認するために頭を回すのと同じです。一度あなたの頭を元に戻すと、あなたはもはや見ていないところで起こっていることを推測するだけです。ファイルを開いたままにしておくと、運転時に(良好または悪い場合)可能ではない、一貫した状態の延長が保証されます。 :)

try/openを使用するのではなくファイルが存在しないかどうかの確認は、スナップショットの性質がos.path.existsであるため、依然として不十分です。残念ながら、すべての場合にディレクトリ内にファイルが作成されるのを防ぐ方法がないので、ファイルがないことを確認することが最善の方法だと思います。

0

私が何を求めていることは、特定の競合状態だと思う:

  • コンテキストが切り替えられると、ファイルが
  • コンテキストがスイッチバックされ、ファイル操作が試行され、削除され

    1. ファイルを開いています「開」に

    あなたが任意の時点のファイルであれば、tryブロック内のすべてのファイル処理コードを置くことで、この場合の「保護」している方法を提出アクセス不能/壊れた場合、ファイル操作はcatchブロックを介して「正常に」失敗する可能性があります。当然の

    注意現代のOSのファイルは、ファイル上のすべての開いているハンドルが解決されるまで、削除が(解放)行われません「削除」されたときに、これは、とにかく起こることはできません

  • +1

    @downvoter - reasoning?問題はありますか? – Mike

    関連する問題