2012-10-02 16 views
14

ファイルが削除されたか、またはPythonで再作成されているかどうかを確認できますか?開いているファイルがPythonで開いた後に削除されたかどうか確認してください

たとえば、スクリプト内でopen("file")を実行した後、そのファイルがまだ開いているときにrm file; touch file;を実行すると、スクリプトはすでに削除されていても古いファイルへの参照を保持します。

+0

多分os.path.existsはこの場合動作しますか? – Alex

+2

os.path.existsの問題は、古いファイルが既に削除されていても、同じパス名を持つ別のファイルが存在する可能性があることです。 – user1502906

答えて

4

はい。ファイルの長さを確認するにはthe os.stat() functionを使用してください。長さがゼロの場合(または関数が「ファイルが見つかりません」というエラーを返した場合)、誰かがファイルを削除します。

また、何か書き込む必要があるたびにファイルを開いて+書き込み+閉じることができます。欠点は、ファイルを開くのがかなり遅いことです。だから、たくさんのデータを書く必要があるなら、これは問題ではありません。

なぜですか?新しいファイルはあなたが開いているファイルではないからです。簡単に言えば、Unixファイルシステムには2つのレベルがあります。 1つはディレクトリエントリ(すなわち、ファイル名、ファイルサイズ、変更時刻、データへのポインタ)であり、第2のレベルはファイルデータである。

ファイルを開くと、Unixはその名前を使ってファイルデータを検索します。その後、2番目のレベルでのみ動作します。ディレクトリエントリの変更は、開いている "ファイルハンドル"には影響しません。ディレクトリエントリを削除することができます:あなたのプログラムはそれを使用していません。

os.stat()を使用すると、ファイルデータは表示されず、ディレクトリエントリに再び表示されます。

肯定的な側面では、誰も見ることができないファイルを作成することができます。ファイルを開き、削除してから使用します。ファイルのディレクトリエントリがないので、他のプログラムはデータにアクセスできません。

負の側では、自分の持つような問題を簡単に解決できません。

+1

Linuxでは、 'proc//fd/...'ファイルが削除された場合でもデータは削除されます。あなたがyoutubeからダウンロードしているビデオのコピーを作成したい場合は、便利なことがあります;-) – hochl

+0

ありがとう、私はそれがstatと何か関係があることを知っていた – user1502906

+0

@hochl:面白い。注意:プロセスの 'fd'ディレクトリの内容を読むには、そのユーザまたはroot(権限は' dr-x ------ ')でなければならないので、まだ安全です。 –

3

はい - inotify機能を使用して、ファイルの変更などを確認できます。また、Python bindingもあります。 inotifyを使うと、ファイルシステムのファイルやディレクトリを見ることができます。次のイベントを検出することができ、マニュアルから:

IN_ACCESS   File was accessed (read) (*). 
IN_ATTRIB   Metadata changed, e.g., permissions, timestamps, extended attributes, link count (since Linux 2.6.25), UID, GID, etc. (*). 
IN_CLOSE_WRITE File opened for writing was closed (*). 
IN_CLOSE_NOWRITE File not opened for writing was closed (*). 
IN_CREATE   File/directory created in watched directory (*). 
IN_DELETE   File/directory deleted from watched directory (*). 
IN_DELETE_SELF Watched file/directory was itself deleted. 
IN_MODIFY   File was modified (*). 
IN_MOVE_SELF  Watched file/directory was itself moved. 
IN_MOVED_FROM  File moved out of watched directory (*). 
IN_MOVED_TO  File moved into watched directory (*). 
IN_OPEN   File was opened (*). 

ここからは自分で解決策をグーグルことができますが、私はあなたの全体的なアイデアを得ると思います。もちろんこれはLinux上でしか動作しないかもしれませんが、あなたの質問から私はあなたがそれを使用していると仮定します(rmtouchへの参照)。

14

開かれたファイルのファイル記述子はfstatです。

>>> import os 
>>> f = open("testdv.py") 
>>> os.fstat(f.fileno()) 
posix.stat_result(st_mode=33188, st_ino=1508053, st_dev=65027L, st_nlink=1, st_uid=1000, st_gid=1000, st_size=1107, st_atime=1349180541, st_mtime=1349180540, st_ctime=1349180540) 
>>> os.fstat(f.fileno()).st_nlink 
1 

このファイルのリンクは1つで、ファイルシステムには1つの名前が付いています。

>>> os.unlink("testdv.py") 
>>> os.fstat(f.fileno()).st_nlink 
0 

これ以上のリンクを、私たちはそれが唯一のkept alive as long as we have it openだ「匿名のファイルを」持っている:今、それを削除。それは、制御設定でけれども(ゼロのため、完全に信頼性がないことを確認し、もちろん

>>> g = open("testdv.py", "w") 
>>> os.fstat(g.fileno()).st_nlink 
1 
>>> os.fstat(f.fileno()).st_nlink 
0 

st_nlinkは時々、最初は>1することができます。同じ名前の新しいファイルを作成し、古いファイルには影響しません十分に良いかもしれない)。代わりに、あなたが最初に開かれたパスにあるファイルは、あなたがstat結果を比較することでのファイル記述子を持っているものと同じであるかどうかを確認することができます

>>> os.stat("testdv.py") == os.fstat(f.fileno()) 
False 
>>> os.stat("testdv.py") == os.fstat(g.fileno()) 
True 

(そして、あなたが、これは100%正しいことをしたい場合は、他のフィールドと特にがコール間で変更される可能性があるので、statの結果のst_devフィールドとst_inoフィールドのみを比較する必要があります。

関連する問題