Python: как создать постоянную структуру в памяти для отладки - PullRequest
3 голосов
/ 16 ноября 2010

[Python 3.1]

Запуск моей программы занимает много времени только из-за метода pickle.load для огромной структуры данных.Это делает отладку очень раздражающей и отнимает много времени: каждый раз, когда я делаю небольшое изменение, мне нужно ждать несколько минут, чтобы проверить, пройдены ли регрессионные тесты.

Я хотел бы заменить pickle на вход- структура данных памяти.

Я думал о запуске программы на Python в одном процессе и подключении к нему из другого;но я боюсь, что издержки межпроцессного взаимодействия будут огромными.

Возможно, я мог бы запустить функцию python из интерпретатора для загрузки структуры в память.Затем, изменяя остальную часть программы, я могу запустить ее много раз (не выходя из интерпретатора между ними).Кажется, это сработает, но я не уверен, что у меня возникнут какие-либо накладные расходы или возникнут другие проблемы.

Ответы [ 2 ]

1 голос
/ 16 ноября 2010

Вы можете использовать mmap, чтобы открыть представление одного и того же файла в нескольких процессах с доступом почти со скоростью памяти после загрузки файла.

0 голосов
/ 16 ноября 2010

Сначала вы можете травить различные части объекта отверстия, используя этот метод:

# gen_objects.py

import random
import pickle

class BigBadObject(object):
   def __init__(self):
      self.a_dictionary={}
      for x in xrange(random.randint(1, 1000)):
         self.a_dictionary[random.randint(1,98675676)]=random.random()
      self.a_list=[]
      for x in xrange(random.randint(1000, 10000)):
         self.a_list.append(random.random())
      self.a_string=''.join([chr(random.randint(65, 90)) 
                        for x in xrange(random.randint(100, 10000))])

if __name__=="__main__":
   output=open('lotsa_objects.pickled', 'wb')
   for i in xrange(10000):
      pickle.dump(BigBadObject(), output, pickle.HIGHEST_PROTOCOL)
   output.close()

После того, как вы сгенерировали BigFile в различных отдельных частях, вы можете прочитать его с помощью программы на Python, в которой несколько запущенных одновременно читают разные части.

# reader.py

from threading import Thread
from Queue import Queue, Empty
import cPickle as pickle
import time
import operator

from gen_objects import BigBadObject

class Reader(Thread):
   def __init__(self, filename, q):
      Thread.__init__(self, target=None)
      self._file=open(filename, 'rb')
      self._queue=q
   def run(self):
      while True:
         try:
            one_object=pickle.load(self._file)
         except EOFError:
            break
         self._queue.put(one_object)

class uncached(object):
   def __init__(self, filename, queue_size=100):
      self._my_queue=Queue(maxsize=queue_size)
      self._my_reader=Reader(filename, self._my_queue)
      self._my_reader.start()
   def __iter__(self):
      while True:
         if not self._my_reader.is_alive():
            break
         # Loop until we get something or the thread is done processing.
         try:
            print "Getting from the queue. Queue size=", self._my_queue.qsize()
            o=self._my_queue.get(True, timeout=0.1) # Block for 0.1 seconds 
            yield o
         except Empty:
            pass
      return

# Compute an average of all the numbers in a_lists, just for show.
list_avg=0.0
list_count=0

for x in uncached('lotsa_objects.pickled'):
   list_avg+=reduce(operator.add, x.a_list)
   list_count+=len(x.a_list)

print "Average: ", list_avg/list_count

Этот способ чтения файла рассола займет 1% времени, который требуется другим способом. Это потому, что вы запускаете 100 параллельных потоков одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...