用于处理大型结果集的生成器

时间:2014-02-13 11:21:27

标签: python-3.x sqlite generator

我正在从sqlite数据库中检索信息,这些信息可以让我回溯大约需要处理的2000万行。然后将此信息转换为我需要使用的列表。我试图尽可能使用发电机。

有人可以看看这段代码并建议优化吗?我要么得到“被杀”的消息,要么需要很长时间才能运行。 SQL结果集部分工作正常。我在Python解释器中测试了生成器代码,它没有任何问题。我猜这个问题与dict生成有关。

编辑/更新清晰度:

我的sqlite数据库中的结果集中有2000万行。每行的格式为:

(2786972, 486255.0, 4125992.0, 'AACAGA', '2005’)

我现在需要创建一个用行的第四个元素“AACAGA”键入的字典。 dict将保存的值是第三个元素,但它必须保存结果集中所有出现的值。因此,在我们的例子中,'AACAGA'将包含一个包含sql结果集中多个值的列表。这里的问题是在基因组序列中发现串联重复。串联重复是基因组读数('AACAGA'),其连续重复至少三次。为了计算这个,我需要将第三个索引中的所有值作为基因组读取的列表,在我们的案例中为“AACAGA”。一旦我有了列表,我可以减去列表中的连续值,看看是否有三个连续的匹配读取的长度。这就是我打算用字典和列表作为值来实现的目标。

#!/usr/bin/python3.3
import sqlite3 as sql

sequence_dict = {}
tandem_repeat = {}

def dict_generator(large_dict):
     dkeys = large_dict.keys()
     for k in dkeys:
         yield(k, large_dict[k])

 def create_result_generator():
     conn = sql.connect('sequences_mt_test.sqlite', timeout=20)
     c = conn.cursor()
     try:
         conn.row_factory = sql.Row
         sql_string = "select * from sequence_info where kmer_length > 2"
         c.execute(sql_string)
     except sql.Error as error:
         print("Error retrieving information from the database : ", error.args[0])
     result_set = c.fetchall()
     if result_set:
         conn.close()
         return(row for row in result_set)

 def find_longest_tandem_repeat():
     sortList = []
     for entry in create_result_generator():
         sequence_dict.setdefault(entry[3], []).append(entry[2])

     for key,value in dict_generator(sequence_dict):
         sortList = sorted(value)
         for i in range (0, (len(sortList)-1)):
             if((sortList[i+1]-sortList[i]) == (sortList[i+2]-sortList[i+1])
                 == (sortList[i+3]-sortList[i+2]) == (len(key))):
                   tandem_repeat[key] = True
                   break

     print(max(k for k, v in tandem_repeat.items() if v))

 if __name__ == "__main__":
     find_longest_tandem_repeat()

1 个答案:

答案 0 :(得分:0)

我在codereview上得到了一些帮助,正如@hivert建议的那样。谢谢。这在SQL中更好地解决,而不仅仅是代码。我是SQL的新手,因此无法编写复杂的查询。有人帮我解决了这个问题。

SELECT *
    FROM sequence_info AS middle
        JOIN sequence_info AS preceding
            ON preceding.sequence_info = middle.sequence_info
            AND preceding.sequence_offset = middle.sequence_offset -
                length(middle.sequence_info)
        JOIN sequence_info AS following
            ON following.sequence_info = middle.sequence_info
            AND following.sequence_offset = middle.sequence_offset + 
                length(middle.sequence_info)
    WHERE middle.kmer_length > 2
    ORDER BY length(middle.sequence_info) DESC, middle.sequence_info, 
        middle.sequence_offset;

希望这可以帮助有同样想法的人。 Here是codereview.stackexchange.com上线程的链接