2011-01-30 6 views
2

私はLinux上で動作するPythonアプリケーションを持っています。 cronから毎分呼び出されます。ディレクトリのファイルをチェックし、ファイルが見つかった場合はそれを処理します。これには数分かかることがあります。私は次のcronジョブが現在処理中のファイルを受け取ることを望んでいないので、以下のコードを使用してロックします。問題は、それがうまくいかないことです。次のcronジョブは、処理可能なすべてのファイルに対して返されたファイルハンドルを取得します。Python:ファイルをロックする

def open_and_lock(full_filename): 
    file_handle = open(full_filename, 'r') 
    try: 
     portalocker.lock(file_handle, portalocker.LOCK_EX 
          | portalocker.LOCK_NB) 
     return file_handle 
    except IOError: 
     sys.exit(-1) 

他のプロセスがそれを取得できないようにファイルをロックするために何ができるのですか? @Winstonエバートへ

UPDATE

おかげで私は、コードをチェックし、処理が終わっていた前に、ファイルハンドルが閉じられた方法であることがわかりました。これは、例外を投げるのではなく、portalocker.lockの2番目のプロセスブロックを除いて現在動作しているようです。

+0

ファイルをロックする管理プロセスはありますか。 –

+0

私はこの呼び出しから返され、ファイルを読み取るのでyesと言うことができます – Ambrosio

+0

この関数から返されるファイルハンドルはどうしますか? –

答えて

0

私はfcntl.lockfがあなたが探しているものだと思います。

2

ロックするファイルの横に古い形式の.lock -fileを手動で作成するとどうなりますか?

それが存在するかどうかを確認してください。もしそうでなければ作成し、そうであれば早期に終了する。終了後、削除してください。

+0

注意:この回答は間違っています!競合状態が待ち受けています... –

+0

この回答は正しい(正しく行われました)。読み取り専用ファイルを作成します(検査は暗黙的です)。すでに存在する場合はエラーを返します。 – darkfeline

+1

多くのプログラムがSkypeやTruecryptのようなこの技術を使用しています。彼らはまた、クラックや予期せずシャットダウンした場合、エンドユーザーはすべての.lockファイルを見つけて削除する必要があるという欠点を共有しています。これは絶対に間違っているので、適切なロックライブラリを使用してください。 –

5

LOCK_NBフラグを使用しています。これは、コールが非ブロッキングであることを意味し、失敗した場合にただちに戻ります。おそらく第2のプロセスで起こっていることでしょう。まだファイルを読み取ることができる理由はで述べたようにportalockerは最終的に、群れ(2)ロックを使用して、ということですflock(2) man page

勧告的ロックを配置します(2)群れのみ。 ファイルに適切なアクセス許可が与えられている場合、 プロセスは、 flock(2)の使用を無視して、そのファイルに対してI/Oを実行することは自由です。あなたはロックが成功したかどうかを確認するために、直接fcntl.flock機能を使用する(portalockerは、Linux上でその周りだけ薄いラッパーである)と、戻り値をチェックすることができ、それを修正するには

2

これにはcronを使用しないでください。 Linuxにはinotifyがあり、ファイルシステムイベントが発生したときにアプリケーションに通知することができます。 pyinotifyと呼ばれるinotifyのPythonバインディングがあります。

このように、ファイルをロックする必要はありません。つまり、書き込みのために開いたファイルが閉じられたときに、IN_CLOSE_WRITEイベントに反応するだけです。 (あなたはまた、新しいプロセス毎分を起動する必要はありません。)

pyinotifyを使用する代わりに、あなたと対話するために、incrontab(crontabファイルと同じスタイルで非常に多くを)書くことができますincronですinotifyシステム。

+0

私は既にコメントで解決されていると思いますが、これも役に立つアドバイスです。 –

+0

これらの通知に反応するためにデーモンプロセスを実行する必要がありますか? – Ambrosio

+0

@Ambrosio:はい、pyinotifyを使用する場合、Pythonアプリケーションが実行されていなければなりません。また、 'incron'を使用すると、' incrond'デーモンが実行されている必要があります。それでも、1分ごとに 'cron' + 1プロセスを使うよりも、リソースの消費量が少ないと思います。 – unutbu

1

多くのスキームでぼんやりとした後、これは私のケースでは機能します。私は同時に複数回実行されるかもしれないスクリプトを持っています。いくつかのファイルを読み書きするためには、これらのインスタンスが必要です。ロックファイルを削除する必要はありません。したがって、削除する前に1つのスクリプトが失敗した場合、すべてのアクセスをブロックすることは避けてください。

import fcntl 

def acquireLock(): 
    ''' acquire exclusive lock file access ''' 
    locked_file_descriptor = open('lockfile.LOCK', 'w+') 
    fcntl.lockf(locked_file_descriptor, fcntl.LOCK_EX) 
    return locked_file_descriptor 

def releaseLock(locked_file_descriptor): 
    ''' release exclusive lock file access ''' 
    locked_file_descriptor.close() 

lock_fd = acquireLock() 

# ... do stuff with exclusive access to your file(s) 

releaseLock(lock_fd) 
関連する問題