cat_baxter

external merge sort

Jul 11th, 2014
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.90 KB | None | 0 0
  1. import time
  2. import sys
  3. import os
  4. from heapq import heappop, heappush
  5. from itertools import islice
  6. from tempfile import gettempdir
  7.  
  8. LINES_BUFFER = 2000  # 1MB / 502 bytes
  9. KB_64 = 64 * 1024
  10.  
  11.  
  12. def merge(chunks):
  13.     key = lambda x: x
  14.     values = []
  15.     for index, chunk in enumerate(chunks):
  16.         try:
  17.             iterator = iter(chunk)
  18.             value = iterator.next()
  19.         except StopIteration:
  20.             try:
  21.                 chunk.close()
  22.                 os.remove(chunk.name)
  23.                 chunks.remove(chunk)
  24.             except:
  25.                 pass
  26.         else:
  27.             heappush(values, (key(value), index, value, iterator, chunk))
  28.  
  29.     while values:
  30.         k, index, value, iterator, chunk = heappop(values)
  31.         yield value
  32.         try:
  33.             value = iterator.next()
  34.         except StopIteration:
  35.             try:
  36.                 chunk.close()
  37.                 os.remove(chunk.name)
  38.                 chunks.remove(chunk)
  39.             except:
  40.                 pass
  41.         else:
  42.             heappush(values, (key(value), index, value, iterator, chunk))
  43.  
  44.  
  45. def external_sort(input_file, output_file):
  46.     temp_dir = gettempdir()
  47.     input_file = file(input_file, 'rb', KB_64)
  48.     try:
  49.         input_iterator = iter(input_file)
  50.         chunks = []
  51.         output_chunk = None
  52.         try:
  53.             while True:
  54.                 current_chunk = list(islice(input_iterator, LINES_BUFFER))
  55.                 if current_chunk:
  56.                     current_chunk.sort()
  57.                     output_chunk = file(os.path.join(temp_dir, '%06i' % len(chunks)), 'w+b', KB_64)
  58.                     output_chunk.writelines(current_chunk)
  59.                     output_chunk.flush()
  60.                     output_chunk.seek(0)
  61.                     chunks.append(output_chunk)
  62.                 else:
  63.                     break
  64.         except:
  65.             for chunk in chunks:
  66.                 try:
  67.                     chunk.close()
  68.                     os.remove(chunk.name)
  69.                 except:
  70.                     pass
  71.             if output_chunk not in chunks:
  72.                 try:
  73.                     output_chunk.close()
  74.                     os.remove(output_chunk.name)
  75.                 except:
  76.                     pass
  77.             return
  78.     finally:
  79.         input_file.close()
  80.  
  81.     output_file = file(output_file, 'wb', KB_64)
  82.     try:
  83.         output_file.writelines(merge(chunks))
  84.     finally:
  85.         for chunk in chunks:
  86.             try:
  87.                 chunk.close()
  88.                 os.remove(chunk.name)
  89.             except:
  90.                 pass
  91.         output_file.close()
  92.  
  93.  
  94. if __name__ == '__main__':
  95.     t = time.time()
  96.     if len(sys.argv) < 2:
  97.        print("Input [output] file(s) please....")
  98.     else:    
  99.        external_sort(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else "%s.out" % sys.argv[1])
  100.        print("Sorted in %f sec." % (time.time() - t))
Add Comment
Please, Sign In to add comment