2012-01-21 15 views
0

を構築(辞書(dictの()))すなわち、異なる番号が付けられたディレクトリに格納されている複数のファイル、Pythonは - 効率的に私は辞書を構築しようとしています辞書

/data/server01/datafile01.dat 
/data/server01/datafile02.dat 
... 
/data/server02/datafile01.dat 
/data/server02/datafile02.dat 
... 
/data/server86/datafile01.dat 
... 
/data/server86/datafile99.dat 

のうち、私はカップルの問題を抱えています現時点では:ディレクトリ

の切り替え

  1. 私は86サーバを持っていることを知っているが、サーバーごとのファイル数は異なる場合があります。私は使用しています:

    for i in range(1,86): 
        basedir='/data/server%02d' % i 
        for file in glob.glob(basedir+'*.dat'): 
         Do reading and sorting here 
    

    しかし、私は正しくディレクトリを切り替えるようです。それはちょうど最初の一つに座って、キーが既に私が何とかキーかどうかを確認する機能を持っていると思い

が存在するかどうかの確認ディレクトリ

  1. でファイルがないときそれはそう立ち往生すでに存在であるか、またはしない、および場合、それは、カントが辞書を定義する1つため、キーと特定のサブキーこと作成ありえ[キー1] [SUBKEY1] [Subsubkey1] =値iが

+1

'basedir'とあなたのglobの間に'/'がありません。 – katrielalex

+0

パスを構築するには 'os.path.join'を使うべきです。 –

+0

組み込みの 'file'もシャドーしないでください。 – katrielalex

答えて

2

Björnは質問の半分をdefaultdictと助けました。彼の提案は、まだ存在していないキーのデフォルト値に関してあなたがしたいところに非常に近くなるはずです。

ディレクトリをウォークしてファイルを見るのに最適なツールはos.walkです。ディレクトリ名とファイル名を組み合わせてos.path.joinとすると、興味のあるファイルを見つけることができます。このようなもの:

import os 

data_path = '/data' 

# option 1 using nested list comprehensions** 
data_files = (os.path.join(root,f) for (root, dirs, files) in os.walk(data_path) 
            for f in files) # can use [] instead of() 

# option 2 using nested for loops 
data_files = [] 
for root, dirs, files in os.walk(data_path): 
    for f in files: 
     data_files.append(os.path.join(root, f)) 

for data_file in data_files: 
    # ... process data_file ... 

** list comprehensionsのドキュメント。

2

のPython 2.6.6を使用していBTW

私はあなたの最初の問題であなたを助けることはできません、 2つ目はdefaultdictを使用して解決できます。これは、要求されたキーが存在しないときに値を生成するために呼び出される関数を持つ辞書です。私はこれらの「ディレクトリ」を仮定している

>>> your_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(int))) 
>>> your_dict[1][2][3] 
0 
+3

無限のネスティングのために 'def default():return defaultdict(default)'を使うことができます。再帰! – Robin

1

リモートで株式を搭載している:あなたが巣彼らがすることができlambdaを使用していますか?物事の

カップル:

  1. 私はそれらの時を回避するために multiprocessing.Poolを用いた演算を並列に非常に良い結果を持っていたFS関連のものについてos.path.join代わりの'basedir' + '*.dat'
  2. を使用したいですリモートfsは非常に遅く、プロセス全体を保持します。他の回答で述べた、あるいはあなた自身の辞書のサブクラス、または関数としてあなたのdict関連の問題については

    import os 
    import glob 
    import multiprocessing as mp 
    
    def processDir(path): 
        results = {} 
        for file in glob.iglob(os.path.join(path,'*.dat')): 
         results.update(add to the results here) 
        return results 
    
    dirpaths = ['/data/server%02d'%i for i in range(1,87)] 
    _results = mp.Pool(8).map(processDir,dirpaths) 
    results = combine _results here... 
    

defaultdictでしょうか?

def addresult(results,key,subkey,subsubkey,value): 
    if key not in results: 
     results[key] = {} 
    if subkey not in results[key]: 
     results[key][subkey] = {} 
    if subsubkey not in results[key][subkey]: 
     results[key][subkey][subsubkey] = value 

これを達成するための効率的な方法はほぼ確実ですが、これが始まりです。