Python - 有效地构建字典

时间:2012-01-21 18:54:08

标签: python

我正在尝试用多个文件构建一个dict(dict(dict())),这些文件存储在不同的编号目录中,即

/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. 在目录之间切换
  2. 我知道我有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. 检查密钥是否已存在
    2. 我想有一个函数以某种方式检查一个密钥是否已经存在,并且如果它没有创建该密钥和某些子密钥,因为一个不能定义dict [Key1] [Subkey1] [Subsubkey1] = value

      BTW我正在使用Python 2.6.6

3 个答案:

答案 0 :(得分:2)

我无法帮助解决您的第一个问题,但第二个问题可以通过使用defaultdict来解决。这是一个字典,其函数被调用以在请求的密钥不存在时生成值。使用lambda可以嵌套它们:

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

答案 1 :(得分: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 :(得分:1)

我假设这些'目录'是远程挂载的共享?

一些事情:

  1. 我使用os.path.join代替'basedir' + '*.dat'
  2. 对于FS相关的东西,我已经有很好的结果并行计算使用 multiprocessing.Pool绕过那些远程fs可能非常慢并且阻碍整个过程的时间。

    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...
    
  3. 对于与dict相关的问题,请使用其他答案中提到的defaultdict,甚至是您自己的dict子类或函数?

    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
    

    几乎可以肯定有更有效的方法来实现这一目标,但这是一个开始。