2012-05-05 17 views
0

おはようございます。私は、JPEG画像からEXIFデータを収集し、Python v2.xを使用してMySQLデータベースに格納するコードを開発しようとしています。障害は、JPEGがいくつかのサブディレクトリとルートのさらなるサブディレクトリに散在しているという事実にありますroot> subroot> subsubroot1に200個のJPEGが格納され、さらにroot> subroot> subroot2に100個のJPEGが格納されます。すべてのイメージが特定されると、イメージがスキャンされ、それぞれのEXIFデータが抽出されてからMySQLテーブルに追加されます。再帰的な検索とMySqlの比較

現時点で私は計画段階にありますが、再帰的検索を実行するには最も効率的で無作法な方法は何でしょうか?私は、ルートディレクトリをスキャンし、新しい識別されたサブディレクトリをリストに追加し、すべてのディレクトリのリストを表示するまで、リスト内のすべてのサブディレクトリパスをさらにサブディレクトリにスキャンします。 IMHOと少し繰り返しているので、これは不器用なようですが、この機能を実行するよりOOPの方法があるかもしれないと思います。

同様に、私は自分のMySQLテーブルに新しい情報を追加しようとしているだけなので、エントリがすでに存在するかどうかを確認する最も効率的な方法は何でしょうか?テーブル内のファイル名とJPEGファイル名の両方がMD5ハッシュ値になります。私は、コードの始めにテーブルをスキャンし、すべてのファイル名をセットに入れることを検討していました。新しいJPEGをスキャンする前に、エントリがすでにセットに存在する場合は、EXIFを抽出して次の写真。しかしこれは効率的な方法ですか、新しい画像に遭遇したときにMySQLテーブルをスキャンする方が良いでしょうか?私は、setメソッドがもっとも効率的かもしれないと予想しますが、テーブルには最終的に何千万ものエントリが潜在的に含まれる可能性があるため、これらのエントリのファイル名をセット(揮発性メモリ)に追加するのがベストアイデアではないかもしれません。

ありがとうございました。

答えて

2

すべてのファイルをディレクトリでスキャンする機能を作成するだけです。それがjpegの場合は、jpegのフルパス名を結果のリストに追加します。ディレクトリの場合は、新しく検出されたディレクトリを引数としてすぐに関数を呼び出します。それが別の種類のファイルであれば、何もしないでください。これは古典的な反復的な分割・征服戦略です。例えば、シンボリックリンクのように、あなたのディレクトリパスにループがあると、それが壊れます。これが危険な場合は、 "本当の"ものを見つけて同じディレクトリを2回はトラバースしないようにする必要があります-symlinked各ディレクトリのパスとそれを記録します。

重複したエントリを避けるには、やりがいのある問題があります。同じ内容の2つの異なる名前のファイルに寛容であるかどうかを検討する必要があります(symlinkedまたはmultiply-hard-linkedファイルのエッジケースも考慮してください) 、スキャンしているディレクトリに新しいファイルがどのように表示されるか、そのプロセスを制御できるかどうかを確認します。それをスピードアップするアイデアは、os.path.getmtime()を使用することです。ディレクトリトラバーサルプロセスを開始した瞬間を記録します。次回は、あなたの記録された時間よりも古いmtimeのjpegファイルを再帰トラバーサルプロセスで無視してください。これは、プロセスの開始時刻と終了時刻の間で変更されたファイルが記録される場合と記録されない場合があるため、記録を保持する唯一の方法ではありません。したがって、それらのレコードをデータベースでチェックする必要があります(たとえば、ファイル情報のハッシュやデータ自体のハッシュは、あなたが許容できない複製の種類に応じて)、ヒューリスティックとして使用するとプロセスを大幅に高速化するはずです。

理論上は、データベースからメモリにファイル名ではなくパス名を読み込んで比較を高速化できますが、テーブルが非常に大きくなる危険がある場合は、その情報をデータベースに残すほうがよいでしょう。たとえば、ファイル名からハッシュを作成し、それをUNIQUE制約付きのデータベースに追加するだけで、データベースは重複したエントリを拒否します。例外をキャッチして行きます。前述のヒューリスティックチェックファイルmtimeを使用すると、これは遅くなることはありません。

あなたのアプリケーションにとって重要な場合は、変更のみ可能で新しく作成されない可能性があることを考慮してください。