我正在尝试用多个文件构建一个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
我现在有几个问题:
我知道我有86台服务器,但每台服务器的文件数量可能会有所不同。我正在使用:
for i in range(1,86):
basedir='/data/server%02d' % i
for file in glob.glob(basedir+'*.dat'):
Do reading and sorting here
但我似乎无法正确切换目录。它只是位于第一个并且在目录
中没有文件时似乎卡住了我想有一个函数以某种方式检查一个密钥是否已经存在,并且如果它没有创建该密钥和某些子密钥,因为一个不能定义dict [Key1] [Subkey1] [Subsubkey1] = value
BTW我正在使用Python 2.6.6
答案 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)
我假设这些'目录'是远程挂载的共享?
一些事情:
os.path.join
代替'basedir' + '*.dat'
对于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...
对于与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
几乎可以肯定有更有效的方法来实现这一目标,但这是一个开始。