Как запустить и остановить процесс, используя многопроцессорность? - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь написать простой скрипт, который поможет мне запустить и остановить воспроизведение видео на нескольких Raspberry Pi с помощью mqtt.

Это первый раз, когда я пытаюсь запустить и остановить подпроцесс из сценарий python и у меня возникают проблемы с пониманием правильного порядка операций

есть мой код

import paho.mqtt.client as mqtt
import multiprocessing, time, signal
import os

def player(video):
    print("Playing " + video)
    os.system("omxplayer-sync " + video)

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("player/#")

def on_message(client, userdata, msg):    
    print(msg.topic+" "+str(msg.payload))
    if msg.topic == "player/PLAY":
        p = multiprocessing.Process(target=player, args=[str(msg.payload.decode())])
        p.start()
    if msg.topic == "player/STOP":
        print("Stopping video")
        print(p, p.is_alive())
        print("Terminating video")
        p.terminate()
        print(p, p.is_alive())

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)

client.loop_forever()

Я могу успешно запустить видео, но не могу его остановить. Я почти уверен, что это связано с тем, что объект p уничтожается в конце обратного вызова on_message, но я не вижу, где я могу создать свой процесс в другом месте.


Edit

это наивный подход с использованием глобального ключевого слова

import paho.mqtt.client as mqtt
import multiprocessing, time, signal
import os

videoFile = ""

class GracefulExit:
    kill_now = False
    def __init__(self):
        signal.signal(signal.SIGINT, self.exit_gracefully)
        signal.signal(signal.SIGTERM, self.exit_gracefully)

    def exit_gracefully(self,signum, frame):
        self.kill_now = True

def player():
    global videoFile
    print("Playing " + videoFile)
    os.system("omxplayer-sync " + videoFile)

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("player/#")

def on_message(client, userdata, msg):
    global videoFile
    print(msg.topic+" "+str(msg.payload))
    if msg.topic == "player/PLAY":
        videoFile = str(msg.payload.decode())
        p.start()
    if msg.topic == "player/STOP":
        print("Stopping video")
        print(p, p.is_alive())
        print("Terminating video")
        p.terminate()
        print(p, p.is_alive())

def main():
    app_killer = GracefulExit()
    while not app_killer.kill_now:
        try:
            time.sleep(0.5)
        except BaseException:
            print("Encountered an exeption.")
            break
    print ("End of the program.")

if __name__ == '__main__':
    print("Starting the program")
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect("localhost", 1883, 60)
    client.loop_start()
    p = multiprocessing.Process(target=player)
    main()

, но я могу воспроизвести видео только один раз, и вызов terminate не останавливает воспроизведение


Редактировать 2

Теперь я объявляю p глобальным, как это было предложено, но я не могу понять, как начать воспроизведение имени файла, которое я получаю из подписки MQTT

import paho.mqtt.client as mqtt
import multiprocessing, time, signal
import os

def player():
    print("Playing " + "synctest.mp4")
    os.system("omxplayer-sync " + "synctest.mp4")

p = multiprocessing.Process(target=player)

class GracefulExit:
    kill_now = False
    def __init__(self):
        signal.signal(signal.SIGINT, self.exit_gracefully)
        signal.signal(signal.SIGTERM, self.exit_gracefully)

    def exit_gracefully(self,signum, frame):
        self.kill_now = True

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("player/#")

def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))
    if msg.topic == "player/PLAY":
        print("p.args= " + p.name)
        videoFile = str(msg.payload.decode())
        #how to put the videoFile into the args given to p ?
        p.start()
    if msg.topic == "player/STOP":
        print("Stopping video")
        print(p, p.is_alive())
        print("Terminating video")
        p.terminate()
        print(p, p.is_alive())

def main():
    app_killer = GracefulExit()
    while not app_killer.kill_now:
        try:
            time.sleep(0.5)
        except BaseException:
            print("Encountered an exeption.")
            break
    print ("End of the program.")

if __name__ == '__main__':
    print("Starting the program")
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect("localhost", 1883, 60)
    client.loop_start()
    main()
...