Травление себя и возврат в рабочее состояние?

Я нашел следующий пост чрезвычайно полезным: Как замариновать себя?

однако ограничение этого решения заключается в том, что при перезагрузке класса он не возвращается в свое состояние «времени выполнения». то есть он перезагрузит все переменные и т. д., а также общее состояние класса на момент его сброса... но с этого момента он не продолжит работу.

Рассмотреть возможность:

class someClass(object):
   def doSomething(self):
       i = 0         
       while i <= 20:
          execute
          i += 1
          if i == 10:
             self.dumpState()

   def dumpState(self):
      with open('somePickleFile','wb') as handle:
         pickle.dump(self, handle)

   @classmethod
   def loadState(cls, file_name):
      with open(file_name, 'rb') as handle:
          return pickle.load(handle)

Если вышеописанное выполняется, создав экземпляр someClass:

 sC = someClass()
 sC.doSomething()
 sC.loadState('somePickleFile')

Это не возвращает класс в его состояние времени выполнения, он не продолжается в цикле while до тех пор, пока i == 20..

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


person aurobhima    schedule 06.03.2012    source источник


Ответы (3)


Такой подход невозможен только с Pickle и Unpickle, если ваш код не знает об этом.

Pickle может сохранять основные объекты Python и обычные пользовательские классы, которые ссылаются на эти основные типы. Но он не может заморозить информацию о запущенном контексте, как вы хотите.

Python допускает ограниченные (но мощные) способы доступа к контексту работающего кода через его объекты фрейма — вы можете получить объект фрейма с помощью вызова «inspect.currentframe» в модуле проверки. Это позволит вам увидеть текущую выполняющуюся строку кода, локальные переменные, содержимое локальных переменных и т. д., но внутри чистого python нет способа, не прибегая к необработанным манипуляциям с памятью структур данных интерпретатора Python для перестроения. объект кадра в середине выполнения и выполнение перехода к нему.

Итак, для этого подхода было бы лучше «заморозить» весь процесс и его структуры данных памяти с помощью операционной системы. способ сделать это (возможно, в Linux есть способ, и он должен работать без файлов/файлов, таких как ресурсы, используемые процессом).

Или, изнутри Python, как вы хотите, вы должны вести «проверку книги» всех ваших данных о состоянии таким образом, чтобы Пикл мог «увидеть это». В вашем базовом примере вы должны реорганизовать свой код примерно так:

class someClass(object):
   def setup(self):
       self.i = 0
   def doSomething(self):       
       while self.i <= 20:
          execute
          i += 1
          if i == 10:
             self.dumpState()
   ...
  @classmethod
   def loadState(cls, file_name):
      with open(file_name, 'rb') as handle:
          self = pickle.load(handle)
      if self.i <= 20: # or other check for "running context"
          return self.doSomething()

Фундаментальное отличие здесь заключается в учете локальной переменной "i" в качестве объектной переменной и в отдельном коде инициализации. Таким образом, все состояние, необходимое для продолжения выполнения — для этого небольшого примера — записывается в атрибутах объекта, которые можно правильно мариновать.

person jsbueno    schedule 06.03.2012
comment
Спасибо .. Я попробовал это, и в целом это работает для того, что мне нужно ... спасибо. - person aurobhima; 07.03.2012
comment
Только что получил электронное письмо в списках Python со связанным объектом — проверьте bugs.python.org/issue14288 - вполне может быть, что python 3.3 может добавить поддержку итераторов травления и упростить процесс травления рабочих состояний. - person jsbueno; 14.03.2012

loadState — это classmethod, возвращающий новый экземпляр someClass (или что-то еще, замаринованное в файле). Поэтому вы должны написать вместо этого:

sC = someClass()
sC.doSomething()
sC = someClass.loadState('somePickleFile')
person Constantinius    schedule 06.03.2012

Я считаю, что pickle сохраняет только значения атрибутов экземпляра, а не внутреннее состояние любых выполняемых методов. Он не сохранит тот факт, что метод выполнялся, и не сохранит значения локальных переменных, как i в вашем примере.

person Pierce    schedule 06.03.2012