Python: какое время жизни у объекта?
От: Посторонним В. Беларусь  
Дата: 14.10.08 08:11
Оценка:
def f():
    someObj = SomeClass()
    ...
    # тут куча кода не использующего someObj
    ...
    print "exiting f()"
    retuurn True

У меня не много опыта с языками с garbage colector-ом, потому возник такой вопрос.
Есть ли гарантия того, что деструктор someObj не вызовется по крайней мере до выхода из функции f()?
Выход из ф-и f() может быть как нормальный return или по исключению.

В качестве бонуса был бы рад указанию на авторитетный источник.


11.12.08 22:38: Перенесено модератором из 'Декларативное программирование' — der Igel
python время жизни у объекта
Re: Python: какое время жизни у объекта?
От: FR  
Дата: 14.10.08 08:30
Оценка: 2 (1) +1
Здравствуйте, Посторонним В., Вы писали:

ПВ>У меня не много опыта с языками с garbage colector-ом, потому возник такой вопрос.

ПВ>Есть ли гарантия того, что деструктор someObj не вызовется по крайней мере до выхода из функции f()?
ПВ>Выход из ф-и f() может быть как нормальный return или по исключению.

Точно не вызовется пока есть хоть одна ссылка. То есть в случае с твоим кодом если нет переприсвоений переменной someObj.
Re: Python: какое время жизни у объекта?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.10.08 09:02
Оценка: 2 (1)
Здравствуйте, Посторонним В., Вы писали:

ПВ>
ПВ>def f():
ПВ>    someObj = SomeClass()
ПВ>    ...
ПВ>    # тут куча кода не использующего someObj
ПВ>    ...
ПВ>    print "exiting f()"
ПВ>    retuurn True
ПВ>

ПВ>У меня не много опыта с языками с garbage colector-ом, потому возник такой вопрос.
ПВ>Есть ли гарантия того, что деструктор someObj не вызовется по крайней мере до выхода из функции f()?

Есть такая гарантия (если никто этот деструктор не вызовет явно). Потому что пока на объект есть хоть одна ссылка из таких источников, как глобальные переменные, локальные переменные функции — его не соберёт. В данном случае есть ссылка из локальных переменных (фрейм функции, который живёт пока не состоялся выход из функции) — значит, доживёт. А вот дальше — зависит от других ссылок, и время жизни после выхода из функции не определено.

ПВ>Выход из ф-и f() может быть как нормальный return или по исключению.


Это несущественно, любой выход здесь даст один и тот же результат.

ПВ>В качестве бонуса был бы рад указанию на авторитетный источник.


Да в общем-то из родной документации это всё ясно (почитать хотя бы про модуль gc), хотя может быть не сказано столь явно.
The God is real, unless declared integer.
Re: Python: какое время жизни у объекта?
От: Аноним  
Дата: 14.10.08 11:38
Оценка:
Здравствуйте, Посторонним В., Вы писали:

ПВ>У меня не много опыта с языками с garbage colector-ом, потому возник такой вопрос.

ПВ>Есть ли гарантия того, что деструктор someObj не вызовется по крайней мере до выхода из функции f()?
Раз немного опыта с питоном, непрошеный бесплатный совет: деструкторов у объектов быть не должно.
Re: Python: какое время жизни у объекта?
От: Аноним  
Дата: 14.10.08 17:14
Оценка: -1
Здравствуйте, Посторонним В., Вы писали:

ПВ>
ПВ>def f():
ПВ>    someObj = SomeClass()
ПВ>    ...
ПВ>    # тут куча кода не использующего someObj
ПВ>    ...
ПВ>    print "exiting f()"
ПВ>    retuurn True
ПВ>

ПВ>У меня не много опыта с языками с garbage colector-ом, потому возник такой вопрос.
ПВ>Есть ли гарантия того, что деструктор someObj не вызовется по крайней мере до выхода из функции f()?
ПВ>Выход из ф-и f() может быть как нормальный return или по исключению.

ПВ>В качестве бонуса был бы рад указанию на авторитетный источник.


Вообще, ИМХО, подобный вопрос автоматически означает, что что-то ты делаешь не так.
Re[2]: Python: какое время жизни у объекта?
От: Посторонним В. Беларусь  
Дата: 14.10.08 18:06
Оценка:
Здравствуйте, http://migmit.vox.com/, Вы писали:

HMV>Здравствуйте, Посторонним В., Вы писали:


...
ПВ>>Есть ли гарантия того, что деструктор someObj не вызовется по крайней мере до выхода из функции f()?
ПВ>>Выход из ф-и f() может быть как нормальный return или по исключению.

HMV>Вообще, ИМХО, подобный вопрос автоматически означает, что что-то ты делаешь не так.


У меня daemon на python-е. Мне нужно чтобы при запуске (конструктор) демон писал свой pid в /var/run/mydaemon.pid, а при выходе удалял бы этот файл (деструктор). Я знаю, что при аварийном завершении (kill -9) файл не удалится (деструктор не вызовется), но для штатных ситуаций хотелось бы, чтобы демон чистил за собой.
Re[3]: Python: какое время жизни у объекта?
От: Cyberax Марс  
Дата: 14.10.08 18:18
Оценка:
Здравствуйте, Посторонним В., Вы писали:

ПВ>У меня daemon на python-е. Мне нужно чтобы при запуске (конструктор) демон писал свой pid в /var/run/mydaemon.pid, а при выходе удалял бы этот файл (деструктор). Я знаю, что при аварийном завершении (kill -9) файл не удалится (деструктор не вызовется), но для штатных ситуаций хотелось бы, чтобы демон чистил за собой.

PID-файлы — это уже забота запускающего скрипта, а не самого демона...

Если хочешь надёжности, то создай SysV-семафор и захватывай его во время работы демона. Или более частый вариант — создай lock-файл и пытайся взять блокировку.
Sapienti sat!
Re[3]: Python: какое время жизни у объекта?
От: budkin  
Дата: 14.10.08 19:33
Оценка:
Здравствуйте, Посторонним В., Вы писали:

ПВ>У меня daemon на python-е. Мне нужно чтобы при запуске (конструктор) демон писал свой pid в /var/run/mydaemon.pid, а при выходе удалял бы этот файл (деструктор).


Насчет демонов -- кроме всем известных множественных граблей, связанных с деструкторами, у питона есть волшебное свойство -- его гц (исторически основанный на подсчете ссылок) не удаляет зацикленные цепочки объектов, если в цепочке есть объект с деструктором. В демоне, по собственному горькому опыту, это чревато бессонными ночами в поисках мемори лика, так что в твоем случае деструктор -- дважды плохая идея
Re[3]: Python: какое время жизни у объекта?
От: MasterZiv СССР  
Дата: 14.10.08 19:57
Оценка: :))
Посторонним В. wrote:

> У меня daemon на python-е. Мне нужно чтобы при запуске (конструктор)

> демон писал свой pid в /var/run/mydaemon.pid, а при выходе удалял бы
> этот файл (деструктор). Я знаю, что при аварийном завершении (kill -9)
> файл не удалится (деструктор не вызовется), но для штатных ситуаций
> хотелось бы, чтобы демон чистил за собой.
Ну зделай ты два метода у этого класса, и вызывай их явно, в одной же
функции у тебя все !
Уже бы давно сделал.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Python: какое время жизни у объекта?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.10.08 20:08
Оценка:
Здравствуйте, budkin, Вы писали:

B>Насчет демонов -- кроме всем известных множественных граблей, связанных с деструкторами, у питона есть волшебное свойство -- его гц (исторически основанный на подсчете ссылок) не удаляет зацикленные цепочки объектов, если в цепочке есть объект с деструктором.


Судя по этому письму, последний раз питон Вы видели не менее 5 лет назад. Возможно, и 10. Всё он удаляет, хоть и не сразу, в отличие от случая, когда счётчик ссылок обнуляется. Читайте документацию и больше не пугайте так на ночь.:))

(Я уж не говорю, что подсчёт ссылок — это свойство CPython и аналогичных реализаций, которыми мир не ограничивается. На Jython, IronPython счётчика ссылок не бывает.)

B> В демоне, по собственному горькому опыту, это чревато бессонными ночами в поисках мемори лика, так что в твоем случае деструктор -- дважды плохая идея :)


Я использую деструкторы и сплю спокойно.
"Доктор, что я не так делаю?" ((c))
The God is real, unless declared integer.
Re[3]: Python: какое время жизни у объекта?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.10.08 20:11
Оценка: 1 (1)
Здравствуйте, Посторонним В., Вы писали:

ПВ>У меня daemon на python-е. Мне нужно чтобы при запуске (конструктор) демон писал свой pid в /var/run/mydaemon.pid, а при выходе удалял бы этот файл (деструктор). Я знаю, что при аварийном завершении (kill -9) файл не удалится (деструктор не вызовется), но для штатных ситуаций хотелось бы, чтобы демон чистил за собой.


Про лок на файле pid'а уже говорили. Но если аварийное завершение замечено и отработано интерпретатором Питона, то достаточно обычного try-finally:

  pidfile = Pidfile()
  try:
     собственно работа
  finally:
     pidfile.delete()


А на все случаи (например, SIGKILL или OOM) ты не напасёшься в любом случае, так что практически более важно не наличие pid-файла самого по себе, а корректные (без обгонов) его проверка и удаление. А для этого проще всего flock() и аналоги.
The God is real, unless declared integer.
Re[5]: Python: какое время жизни у объекта?
От: budkin  
Дата: 14.10.08 20:31
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, budkin, Вы писали:


B>>Насчет демонов -- кроме всем известных множественных граблей, связанных с деструкторами, у питона есть волшебное свойство -- его гц (исторически основанный на подсчете ссылок) не удаляет зацикленные цепочки объектов, если в цепочке есть объект с деструктором.


N>Судя по этому письму, последний раз питон Вы видели не менее 5 лет назад. Возможно, и 10. Всё он удаляет, хоть и не сразу, в отличие от случая, когда счётчик ссылок обнуляется. Читайте документацию и больше не пугайте так на ночь.

Я вот какбе открываю документацию по этой самой ссылке и читаю:

Objects that have __del__() methods and are part of a reference cycle cause the entire reference cycle to be uncollectable, including objects not necessarily in the cycle but reachable only from it. Python doesn’t collect such cycles automatically because, in general, it isn’t possible for Python to guess a safe order in which to run the __del__() methods.

Re[6]: Python: какое время жизни у объекта?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.10.08 20:37
Оценка:
Здравствуйте, budkin, Вы писали:

B>Здравствуйте, netch80, Вы писали:


N>>Здравствуйте, budkin, Вы писали:


B>>>Насчет демонов -- кроме всем известных множественных граблей, связанных с деструкторами, у питона есть волшебное свойство -- его гц (исторически основанный на подсчете ссылок) не удаляет зацикленные цепочки объектов, если в цепочке есть объект с деструктором.


N>>Судя по этому письму, последний раз питон Вы видели не менее 5 лет назад. Возможно, и 10. Всё он удаляет, хоть и не сразу, в отличие от случая, когда счётчик ссылок обнуляется. Читайте документацию и больше не пугайте так на ночь.:))

B>Я вот какбе открываю документацию по этой самой ссылке и читаю:

B>

B>Objects that have __del__() methods and are part of a reference cycle cause the entire reference cycle to be uncollectable, including objects not necessarily in the cycle but reachable only from it. Python doesn’t collect such cycles automatically because, in general, it isn’t possible for Python to guess a safe order in which to run the __del__() methods.


Да, верно — я пропустил часть фразы.:(( Надо больше отдыхать.:( Но Вы сильно сбили с толку упоминанием, что это какое-то особое "волшебное свойство" — потому что это нормально не решается в любом GC. Питоновое размещение в gc.garbage — хорошее решение для того, чтобы как-то этот вопрос потом решить отдельно.

С такими случаями я боролся отдельно: регулярно запускаемая проверка gc.garbage и оповещение мониторинга о том, что что-то появилось. Но явно такой цикл сделать — это надо ещё постараться.
The God is real, unless declared integer.
Re[7]: Python: какое время жизни у объекта?
От: budkin  
Дата: 14.10.08 21:04
Оценка:
Здравствуйте, netch80, Вы писали:

B>>Я вот какбе открываю документацию по этой самой ссылке и читаю:


B>>

B>>Objects that have __del__() methods and are part of a reference cycle cause the entire reference cycle to be uncollectable, including objects not necessarily in the cycle but reachable only from it. Python doesn’t collect such cycles automatically because, in general, it isn’t possible for Python to guess a safe order in which to run the __del__() methods.


N>Да, верно — я пропустил часть фразы.( Надо больше отдыхать. Но Вы сильно сбили с толку упоминанием, что это какое-то особое "волшебное свойство" — потому что это нормально не решается в любом GC. Питоновое размещение в gc.garbage — хорошее решение для того, чтобы как-то этот вопрос потом решить отдельно.

Так вот когда нету деструкторов, это решается легко Потом, неплохой подход в .NET, когда деструкторы в цикле таки вызываются в каком-то произвольном порядке, а все проблемы полностью перекладываются на деструкторописателя. В питоне же можно и не заметить, как объект с деструктором из какой-нибудь сторонней библиотеки попадет в цикл, и привет -- лови потом где память утекает.
Re[8]: Python: какое время жизни у объекта?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.10.08 21:11
Оценка:
Здравствуйте, budkin, Вы писали:

B>Так вот когда нету деструкторов, это решается легко :)


И что? Злоупотреблять деструкторами нельзя, но есть случаи, когда они реально необходимы.

B> Потом, неплохой подход в .NET, когда деструкторы в цикле таки вызываются в каком-то произвольном порядке, а все проблемы полностью перекладываются на деструкторописателя.


Если к этому добавить специальный хук — да, ещё можно понять. Если нет — слишком грубо.

B> В питоне же можно и не заметить, как объект с деструктором из какой-нибудь сторонней библиотеки попадет в цикл, и привет -- лови потом где память утекает.


Следить за gc.garbage. К счастью, по объектам достаточно неплохо видно, откуда они произошли.
The God is real, unless declared integer.
Re[4]: Python: какое время жизни у объекта?
От: Посторонним В. Беларусь  
Дата: 15.10.08 07:59
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, Посторонним В., Вы писали:


ПВ>>У меня daemon на python-е. Мне нужно чтобы при запуске (конструктор) демон писал свой pid в /var/run/mydaemon.pid, а при выходе удалял бы этот файл (деструктор). Я знаю, что при аварийном завершении (kill -9) файл не удалится (деструктор не вызовется), но для штатных ситуаций хотелось бы, чтобы демон чистил за собой.


N>Про лок на файле pid'а уже говорили. Но если аварийное завершение замечено и отработано интерпретатором Питона, то достаточно обычного try-finally:


N>
N>  pidfile = Pidfile()
N>  try:
N>     собственно работа
N>  finally:
N>     pidfile.delete()
N>


N>А на все случаи (например, SIGKILL или OOM) ты не напасёшься в любом случае, так что практически более важно не наличие pid-файла самого по себе, а корректные (без обгонов) его проверка и удаление. А для этого проще всего flock() и аналоги.


Примерно так и делаю. Спасибо за идею с flock().
Логика такая
1. при старте демон читает /var/run/mydaemon.pid
2. если такой файл не существует, он создается, демон записывает туда свой pid и начинает работать
3. если такой файл существует, проверяется есть ли записанный там pid в списке работающих процессов ('ps -axo pid=')
3.1. если pid нет в списке, демон записывает туда свой pid и начинает работать
3.2. если pid есть в списке, демон завершается (не стартует)

Как видно из логики, удаление mydaemon.pid в принципе не обязательно.

def main():
   try:
        daemonize()#  демонизируемся
        pidfile = Pidfile()
        ... тут долго у нудно работаем, объект pidfile нигде не используется
        return 0
    except BaseException, e:
        return -1
    except: 
        return -2

if __name__ == "__main__":
    sys.exit(main())


N> Но если аварийное завершение замечено и отработано интерпретатором Питона, то достаточно обычного try-finally


А разве в этом случае не гарантируется вызов деструктора pidfile? В таком случае try--finally не нужно. Верно?
Re: Python: какое время жизни у объекта?
От: palm mute  
Дата: 15.10.08 08:50
Оценка: 1 (1) +1
Use with-statement, Luke!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.