mpiexec + python + ^ C: __del__ метод не выполняется (и не отслеживается) - PullRequest
0 голосов
/ 26 сентября 2019

У меня есть следующий test_mpi.py скрипт Python:

from mpi4py import MPI
import time

class Foo:
    def __init__(self):
        print('Creation object.')
    def __del__(self):
        print('Object destruction.')

foo = Foo()
time.sleep(10)

Если я выполняю его без обращения к mpiexec, используя простой python test_mpi.py, нажимая CTRL + C через 5 с, я получаю следующий вывод:

ngreiner@Nathans-MacBook-Pro:~/Documents/scratch$ python test_mpi.py 
Creation object.
^CTraceback (most recent call last):
  File "test_mpi.py", line 26, in <module>
    time.sleep(10)
KeyboardInterrupt
Object destruction.
ngreiner@Nathans-MacBook-Pro:~/Documents/scratch$

Если я встраиваю его в выполнение mpiexec, используя mpiexec -np 1 python test_mpi.py, снова нажимая CTRL + C через 5 секунд, я получаю:

ngreiner@Nathans-MacBook-Pro:~/Documents/scratch$ mpiexec -np 1 python test_mpi.py 
Creation object.
^Cngreiner@Nathans-MacBook-Pro:~/Documents/scratch$

Трассировку от python ивыполнение метода __del__ исчезло.Основная проблема для меня - это неисполнение метода __del__, который должен привести к некоторой очистке моего реального приложения.

Любая идея, как я мог бы выполнить метод __del__, когда выполняется Pythonзапущен из mpiexec?

Большое спасибо заранее за помощь,

(Конфигурация моей системы: macOS High sierra 10.13.6, Python 3.7.4, open-mpi 4.0.1,mpi4py 3.0.2.)

Ответы [ 2 ]

0 голосов
/ 28 сентября 2019

После небольшого поиска я нашел решение для восстановления печати трассировки и выполнения метода __del__ при нажатии ^ C во время mpiexec.

Во время обычного выполнения Python (не запускаетсяс помощью mpiexec, запускаемой непосредственно из терминала), нажатие ^ C отправляет сигнал SIGINT питону, который преобразует его в исключение KeyboardInterrupt (https://docs.python.org/3.7/library/signal.html).

Но при нажатии ^ C во время выполнения mpiexec этоэто процесс mpiexec, который получает сигнал SIGINT, и вместо того, чтобы передавать его своим дочерним процессам (например, python), он отправляет своим дочерним процессам сигнал SIGTERM (https://www.open -mpi.org / doc /current / man1 / mpirun.1.php ).

Таким образом, кажется, что питон не реагирует аналогично сигналам SIGINT и SIGTERM.

Обнаруженный мной обходной путь заключается в использованиисигнальный модуль и использовать специальный обработчик для сигнала SIGTERM, который просто вызывает KeyboardInterrupt. Это может быть достигнуто следующими строками:

def sigterm_handler():
    raise KeyboardInterrupt

import signal
signal.signal(signal.SIGTERM, sigterm_handler)

Первый может быть включен вверху исполняемого скрипта Python или, чтобы сохранить это поведение каждый раз, когда python используется с mpiexec и с пакетом mpi4py, вверху файла __init__.py пакета mpi4py.

Эта стратегия может иметь побочные эффекты (о которых я не знаю) и должна использоваться на ваш страх и риск.

0 голосов
/ 26 сентября 2019

За документацию , не гарантируется, что будет вызван del .Так что вам повезло, что он вызывается не-mpi программой.

Для простого случая вы можете использовать try / finally, чтобы быть уверенным, что раздел finally выполняется.Или, в более общем смысле, используйте менеджер контекста

Вот цитата из документации, которая здесь важна:

Не гарантируется, что del *Методы 1015 * () вызываются для объектов, которые все еще существуют при выходе из интерпретатора.

...