for x in records:
data = {}
for y in sObjectName.describe()['fields']
data[y['name']] = x[y['name']]
ls.append(adapter.insert_posts(collection, data))
我想在500个批次中执行代码ls.append(adapter.insert_post(collection, x)),其中x应该包含500个data dicts。我可以使用一个双倍for循环和一个list创建一个包含500个dicts的list a,然后插入它。我可以用下面的方法来做, ,有没有更好的方法?
for x in records:
for i in xrange(0,len(records)/500):
for j in xrange(0,500):
l=[]
data = {}
for y in sObjectName.describe()['fields']:
data[y['name']] = x[y['name']]
#print data
#print data
l.append(data)
ls.append(adapter.insert_posts(collection, data))
for i in xrange(0,len(records)%500):
l=[]
data = {}
for y in sObjectName.describe()['fields']:
data[y['name']] = x[y['name']]
#print data
#print data
l.append(data)
ls.append(adapter.insert_posts(collection, data))
我使用的一般结构是这样的。
worklist = [...]
batchsize = 500
for i in xrange(0, len(worklist), batchsize):
batch = worklist[i:i+batchsize] # the result might be shorter than batchsize at the end
# do stuff with batch
注意,我们使用的是 step
的论点 xrange
来大大简化批处理。
如果你正在处理序列,@nneonneo 的解决方案是你能得到的最好的性能。 如果你想要一个可以处理任意迭代的解决方案,你可以看看一些由 @nneonneo 提出的 itertools 食谱.如石斑鱼。
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return itertools.izip_longest(fillvalue=fillvalue, *args)
我倾向于不用这个,因为它把最后一个组 "填满 "了。None
以使其与其他变量的长度相同。 我通常定义我自己的变体,它没有这种行为。
def grouper2(iterable, n):
iterable = iter(iterable)
while True:
tup = tuple(itertools.islice(iterable, 0, n))
if tup:
yield tup
else:
break
这将产生符合要求大小的元组。 这通常已经足够好了,但是,为了好玩,我们可以写一个生成器,如果我们真的想的话,它可以返回正确大小的懒惰迭代。
我认为这里的 "最佳 "解决方案取决于手头的问题--尤其是原始迭代中的组和对象的大小以及原始迭代的类型。 一般来说,最后这2个配方会发现用处不大,因为它们比较复杂,很少需要。 然而,如果你觉得很冒险,想找点乐子,请继续阅读
为了得到一个懒惰的可迭代而不是元组,我们需要做的唯一真正的修改就是能够 "偷看 "下一个值。islice
看看是否有什么东西在那里。 在这里,我只是偷看的值 - 如果它的丢失。StopIteration
将会升高,这将使发电机停止,就像它正常结束一样。 如果它在那里,我就把它放回去,用 itertools.chain
:
def grouper3(iterable, n):
iterable = iter(iterable)
while True:
group = itertools.islice(iterable, n)
item = next(group) # raises StopIteration if the group doesn't yield anything
yield itertools.chain((item,), group)
但要小心,最后一个功能 只是 "工作",如果你完全穷尽每一个可迭代的产物。之前 继续下一个。 在极端的情况下,如果你没有用尽任何一个迭代项,例如,你会得到 "m "个迭代项,而这些迭代项只能产生一个项目,而不是一个项目。list(grouper3(..., n))
,你会得到 "m "个迭代项,这些迭代项只产生1个项目,而不是 n
(其中 "m "是输入迭代的 "长度")。 这种行为实际上有时会很有用,但通常不会。 如果我们使用itertools的 "消耗 "配方,我们也可以解决这个问题(这也需要引入 collections
除了 itertools
):
def grouper4(iterable, n):
iterable = iter(iterable)
group = []
while True:
collections.deque(group, maxlen=0) # consume all of the last group
group = itertools.islice(iterable, n)
item = next(group) # raises StopIteration if the group doesn't yield anything
group = itertools.chain((item,), group)
yield group
当然可以 list(grouper4(..., n))
将返回空的iterables -- 在下一次调用 "组 "之前没有从 "组 "中提取的任何值。next
(例如,当 for
循环循环回到起点)将永远不会得到收益。
也许是这样的?
l = []
for ii, x in enumerate(records):
data = {}
for y in sObjectName.describe()['fields']
data[y['name']] = x[y['name']]
l.append(data)
if not ii % 500:
ls.append(adapter.insert_posts(collection, l))
l = []
我认为这里没有涉及到一个特殊的情况。假设批处理量是100,而你的列表大小是103,上面的答案可能会漏掉最后3个元素。
list = [.....] 103 elements
total_size = len(list)
batch_size_count=100
for start_index in range(0, total_size, batch_size_count):
end_index = total_size if start_index + batch_size_count > total_size else start_index + batch_size_count
list[start_index:end_index] #Slicing operation
上面的分片列表可以发送给每个方法调用,完成所有元素的执行。