Как завершить многопроцессорный родительский процесс? - PullRequest
0 голосов
/ 11 июля 2019

Как я могу заставить свой дочерний процесс завершить родительский процесс?

Я думал что-то вроде ...

Ребенок получает PID родительского процесса и завершает родительское действие, используя psutil

Вот мой код

from multiprocessing import Process, Value
import keyboard
import sys

def KeyboardScan(v):
    Paused = False
    while True:
        if keyboard.is_pressed('x'):
            v.value = 1
            print("Child Terminate")
            sys.exit()
    #Child process's code

if __name__ == "__main__":
    val = Value('i', 0)
    p = Process(target=KeyboardScan, args=(val,))
    p.start()

    #Parent process's code

Поэтому, если нажата клавиша x, дочерний элемент должен завершить родительский процесс и сам себя.

В этом коде value существует только потому, что изначально в моем родительском процессе был цикл while для проверки значения. Если значение равно 1, оно выполняет sys.exit() в родительском процессе.

Но я пытаюсь избежать использования этого метода.

Есть предложения?

Ответы [ 2 ]

1 голос
/ 11 июля 2019

Вы можете использовать os модуль, чтобы получить ppid, а затем .kill it .

попробуйте это:

from multiprocessing import Process, Value
import keyboard
import os
import signal
import sys
import psutil

def KeyboardScan(v):
    Paused = False
    while True:
        if keyboard.is_pressed('x'):
            v.value = 1
            print("Child Terminate")
            #os.kill(os.getppid(), signal.SIGTERM) # <=== if you don't have psutil
            # below 2 line depend on psutil
            p = psutil.Process(os.getppid())
            p.terminate()  #or p.kill()
            sys.exit()
    #Child process's code

if __name__ == "__main__":
    val = Value('i', 0)
    p = Process(target=KeyboardScan, args=(val,))
    p.start()

    #Parent process's code
0 голосов
/ 11 июля 2019

Подумайте об использовании многопроцессорных примитивов, чтобы обеспечить чистое отключение обоих процессов.Два способа сделать это:

  1. Кодировать дочерний элемент, чтобы просто выйти, когда он обнаружит X. Пусть родитель иногда проверяет, жив ли дочерний процесс, с помощью p.is_alive или p.exitcode.Если это не так, выйдите из
  2. . Переместите обнаружение клавиатуры обратно в родительский процесс.Сигнал о том, что ребенок должен выйти через общий multiprocessing.Event

Вы не сказали, что делает ваш родительский процесс во время работы ребенка.Это влияет на то, какой из этих двух подходов легче использовать.Мне нравится второй подход, потому что он мне подходит.Я предпочел бы, чтобы родительский узел занимался пользовательским вводом, и просто выполнял бы дочерний процесс, который не предполагает взаимодействия с пользователем.

В приведенном ниже фрагменте кода показан второй подход.

from multiprocessing import Process, Event
import atexit
import time
from random import randint

def child_main(e):
    print('Child process booted')
    while True:
        if e.is_set():
            print('Child process got terminate event. Exiting')
            return

        print('Child process doing some important work')
        time.sleep(1.0)

def parent_main():
    print("parent process booting")
    quit_event = Event()
    child = Process(target=child_main, args=(quit_event,))
    print('starting child')
    child.start()

    is_x_pressed = lambda: randint(0,8) == 0
    while True:
        print('Parent doing its thing')
        time.sleep(.5)

        if is_x_pressed():
            print("Parent detected X. Exiting")
            quit_event.set()
            return

if __name__== '__main__':
    def exit_hook():
        print('Parent process atexit handler')
    atexit.register(exit_hook)

    parent_main()
    print('parent exiting __main__')
...