Читай в большом файле и составь словарь

У меня есть большой файл, который мне нужно прочитать и создать словарь. Я бы хотел, чтобы это было как можно быстрее. Однако мой код на python слишком медленный. Вот минимальный пример, который показывает проблему.

Сначала сделайте поддельные данные

paste <(seq 20000000) <(seq 2 20000001)  > largefile.txt

Теперь вот минимальный кусок кода на Python для чтения и создания словаря.

import sys
from collections import defaultdict
fin = open(sys.argv[1])

dict = defaultdict(list)

for line in fin:
    parts = line.split()
    dict[parts[0]].append(parts[1])

Тайминги:

time ./read.py largefile.txt
real    0m55.746s

Однако это не связано с I / O как:

time cut -f1 largefile.txt > /dev/null    
real    0m1.702s

Если я закомментируюdict&nbsp;линия занимает9&nbsp;секунд. Кажется, что почти все время тратится наdict[parts[0]].append(parts[1]).

Есть ли способ ускорить это? Я не против использования Cython или даже C, если это будет иметь большое значение. Или панды могут помочь здесь?

Вот вывод профиля на файл размером 10000000 строк.

python -m cProfile read.py test.data         20000009 function calls in 42.494 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 bisect.py:1(<module>)
        1    0.000    0.000    0.001    0.001 collections.py:1(<module>)
        1    0.000    0.000    0.000    0.000 collections.py:25(OrderedDict)
        1    0.000    0.000    0.000    0.000 collections.py:386(Counter)
        1    0.000    0.000    0.000    0.000 heapq.py:31(<module>)
        1    0.000    0.000    0.000    0.000 keyword.py:11(<module>)
        1   30.727   30.727   42.494   42.494 read.py:2(<module>)
 10000000    4.855    0.000    4.855    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
 10000000    6.912    0.000    6.912    0.000 {method 'split of 'str' objects}
        1    0.000    0.000    0.000    0.000 {open}

Обновить.&nbsp;Можно предположить, что parts [1] - целое число, а parts [0] - короткая строка фиксированной длины.

Мои поддельные данные не очень хороши, так как вы получаете только одно значение за ключ. Вот лучшая версия.

perl -E 'say int rand 1e7, $", int rand 1e4 for 1 .. 1e7' > largefile.txt

Единственная операция, которую я сделаю, - это запрос ключа, чтобы вернуть список значений, связанных с ним.