优化python中的for循环

时间:2013-11-25 05:57:16

标签: python for-loop dictionary

我有一个代码,用于放置数据并将其声明为字典。 我目前在我的for循环中有很长时间,大约需要2万小时,大约有200,000个数据。 如果我有200万个数据,现在我正在考虑更多。

这是我的for循环示例(抱歉变量的命名,这只是我的示例代码):

# Gets the data in database
data_list = self.my_service.get_database_list()

my_dict_list = {}

for item in data_list:
    primary_key = item.primarykey
    value = item.name + item.address + item.age

    my_dict_list[primary_key] = value

这是我的模型/ db获取代码:

def get_database_list(self):
    return self.session.query(
        self.mapper.name,
        self.mapper.addreess,
        self.mapper.age,
        )

我的数据库引擎是 InnoDB 。 有没有办法让它有点优化或更快地循环数据。 谢谢你的分享。

3 个答案:

答案 0 :(得分:3)

首先,我怀疑你的瓶颈(几个小时)在于python部分。您可以通过生成器和字典理解获得一些改进,但是要多少?寻找20万行的样本:

import base64
import os
def random_ascii_string(srt_len):
    return base64.urlsafe_b64encode(os.urandom(3*srt_len))[0:srt_len]

>>> data = [{'id': x, 'name': random_ascii_string(10), 'age':'%s' % x,
             'address': random_ascii_string(20)} for x in xrange(2*10**5)]

你的方法

>>> timeit.timeit("""
... from __main__ import data
... my_dict_list = {}
... for item in data:
...     my_dict_list[item['id']] = item['name'] + item['address'] + item['age']""",
...         number = 100)
16.727806467023015

列表理解

>>> timeit.timeit("from __main__ import data; "
...    "my_dict_list = { d['id']: d['name']+d['address']+d['age'] for d in data}",
...     number = 100)
14.474646358685249

我怀疑你能在这些优化中找到两个小时。所以你的首要任务是找到你的瓶颈。我建议你看一下你工作的MySQL部分,并可能将其重新分配给:

  • 每个表使用一个单独的inno db文件
  • 如果检索较小的数据部分,则使用索引
  • 在数据库端进行一些评估,例如name + address + age
  • 不要对整个数据进行处理,只检索所需的部分(几个第一行)

答案 1 :(得分:2)

很难猜测代码花费的时间最多。最好的办法是使用cProfile运行它,并检查结果。

python -m cProfile -o prof <your_script> <args...>

这会输出一个名为prof的文件,您可以通过各种方式进行检查,其中最酷的是使用runsnakerun

除此之外,头脑中的dict-comrehension通常比其他选择更快:

my_dict_list = { item.primarykey: item.name + item.address + item.age }

此外,item.name + item.address + item.age做什么(它们都是字符串?)并不完全清楚,但如果您可以考虑更改数据结构,并存储item而不是该组合值,则可能进一步帮助。

答案 2 :(得分:0)

同意以上关于迭代器的评论。您可以尝试使用字典理解来代替循环。

import uuid
import time

class mock:
    def __init__(self):
        self.name = "foo"
        self.address = "address"
        self.age = "age"
        self.primarykey = uuid.uuid4()

data_list = [mock() for x in range(2000000)]

my_dict_list = {}
t1 = time.time()
for item in data_list:
    primary_key = item.primarykey
    value = item.name + item.address + item.age
    my_dict_list[primary_key] = value
print(time.time() - t1)


my_dict_list = {}
t2 = time.time()
new_dict = { item.primarykey: item.name + item.address + item.age for item in data_list }
print(time.time() - t2)