How to pause / resume multiprocessing in Python? - python

So I got an idea to build something like mp3 player. To build that, I used multiprocessing module provided in Python. Here is my code
import multiprocessing
from playsound import playsound
def cp():
playsound('Music.mp3') # play the music
x = multiprocessing.Process(target = cp, daemon = True)
def main():
x.start()
while True and x.is_alive:
u = input("Input: ")
print(u)
if u == "S":
x.terminate()
print("Terminated process")
break
elif u == 'P':
# questioned code
print("Process paused")
elif u == 'R':
# questioned code
print("Process resumed")
if __name__ == '__main__':
main()
The idea is, when the program is executed, the program will automatically play the Music.mp3 file. To control the program, the user must input specific keyword into it.
S to stop the music and exit the program
P to pause the music
R to resuming playing the music
For now, I only know how to code the S option. For the others, I don't have any idea how to code it. So my question is: Is there any idea how to complete the P and R options? Or maybe, is there any idea about how to build the program using another method besides using multiprocessing module?
Thanks for the help

Related

User input prevents multiprocessing segment of code to work on windows

The problem resolves around my multiprocessing segment not working when I have an input question.
I have tried many workaround to the problem but cannot find a solution, except eliminating the input, however I need it to allow others to interact with my tool.
import time
from multiprocessing import Pool
import collections
choice = input("Do you wish to start program? \n")
print("hello")
start_time = time.time()
value = collections.namedtuple('value',['vectx','vecty'])
Values = (value(vectx=0,vecty=5),value(vectx=5,vecty=10),value(vectx=10,vecty=15),value(vectx=15,vecty=20))#,value(vectx=200,vecty=300),value(vectx=300,vecty=400),value(vectx=400,vecty=500),value(vectx=500,vecty=600),value(vectx=600,vecty=700),value(vectx=700,vecty=800),value(vectx=800,vecty=900),value(vectx=900,vecty=1000),value(vectx=1000,vecty=1100),value(vectx=1100,vecty=1200))
print("Start")
def Alter(x):
vectx=x.vectx
vecty=x.vecty
Z=(vectx+vecty)
return(Z)
if choice == "Yes":
print(1)
if __name__ == '__main__':
with Pool(10) as p:
result=p.map(Alter, Values)
new = []
print("end")
print("result Done")
for i in result:
new.append(i)
print( "My program took " +str(time.time() - start_time)+ " to run")
Expected result is program completes.
Your problem is that windows doesn't have fork like Unix based machines. So each process of the Pool running on Windows imports the main file on creation.
So what happens in your program is that each new process asks for input and your programs tangles up with itself. It was a little unclear to me the location of the if __name__ == '__main__':, but the point here is that you need to keep everything that needs to run once there. Put outside of it only important stuff shared between all processes. For example, a working code on windows could be:
import time
from multiprocessing import Pool
import collections
def Alter(x):
vectx = x.vectx
vecty = x.vecty
Z = (vectx + vecty)
return Z
value = collections.namedtuple('value', ['vectx', 'vecty'])
if __name__ == '__main__':
choice = input("Do you wish to start program? \n")
Values = (value(vectx=0,vecty=5),value(vectx=5,vecty=10),value(vectx=10,vecty=15))
if choice == "Yes":
print("Start")
start_time = time.time()
with Pool(10) as p:
result = p.map(Alter, Values)
print("My program took " + str(time.time() - start_time) + " to run")
Gives:
Do you wish to start program?
Yes
Start
My program took 1.9328622817993164 to run
From the docs, under programming guidelines, section Safe importing of main module:
Make sure that the main module can be safely imported by a new Python
interpreter without causing unintended side effects (such a starting a
new process).

Playing sound and a program

What I want to do is get an audio file to play while a def (function) is running.
I've looked it up and seen that threading works but it is wayyyy to complicated for me to work out. Is there a way you guys can explain it to me? I was using winsound to play the audio file, and SND_FILENAME.
Try this:
from multiprocessing import Process
def play():
#winsound stuff
def function():
#functiony stuff
if __name__ == '__main__':
p = Process(target=play)
d = Process(target=function)
p.start()
d.start()

Only trigger thread when value changes (python)

I'm working on something that reads commands from a stream of data. I got stuck trying to work out making a re-usable non-blocking countdown in Python that works off a trigger. So I started a small program w/ just keyboard input and some basic threading to work out the logic. I found a few posts, and this post (How to create a trigger with threading.Timer?) and it was very helpful. But I need some help with another part.
Right now my logic is along the lines of: "Each time the value of command is 1 call start"
How do I update my logic to be:
"if value of command is 1 call start, do not call start again as long as the value of command remains 1.
So its more of a value change detection than a normal if/else, or I have to track a boolean somewhere. I'm just not sure how to approach it.
#! /usr/bin/env python
import time
import threading
import random
from random import randint
import logging
from sys import argv
logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] (%(threadName)-10s) %(message)s')
def countdown(pName,command):
print("{0} countdown - command{1} ".format(pName,command))
retry = 0
while True:
print("{0}:{1}".format(pName,retry))
retry += 1
if retry > randint(5,10):
break
time.sleep(1)
print("{0} ended".format(pName))
def start(pName,command):
print("starting countdown for: ",pName)
t = threading.Thread(target=countdown,args=(pName,command))
t.setName(pName)
t.setDaemon(True)
t.start()
if __name__ == "__main__":
while 1:
command = int(input("[1 or 2] >"))
if command == 1:
start("Salad",command)
elif command == 2:
start("Bingo",command)
This is pretty brute right now, but its just a first past to try and puzzle it out.
Thanks!
You want the function isAlive. First, you'll have to move your thread variable to the main function, so that main has the appropriate scope to call thread.isAlive().
if __name__ == "__main__":
tSalad = threading.Thread()
tBingo = threading.Thread()
while 1:
command = int(input("[1 or 2] >"))
if command == 1 and not tSalad.isAlive():
tSalad = threading.Thread(target = countdown, args=("Salad", 1))
start("Salad", tSalad)
elif command == 2 and not tBingo.isAlive():
tBingo = threading.Thread(target = countdown, args=("Bingo", 2))
start("Bingo", tBingo)
Then you modify your 'start' function to take a thread argument:
def start(pName, t):
print("starting countdown for: ",pName)
t.setName(pName)
t.setDaemon(True)
t.start()
That should do the trick for you.

Running multiple functions at once using multiprocessing

Currently, I am working on a text-based RPG. The idea is to implement a sound track, as well as general sounds for gameplay, along with a gui, eventually. I have figured out how to play sound using a pyaudio. Now, the problem is that I cannot run any other functions while the music is playing. Is there a way around this? I have read threads on multiprocessing; however, they don't seem to be helping much. With out the multiprocessing code, the audio will dominate and Python will not run any other function. With the code, the game will run the game, but no the audio.
#Module Imports
from rooms import user, create
import items
import enemies
import rooms
from music import AudioFile
from multiprocessing import Process
import sys
def game():
global AudioFile
User = user()
c = create()
a = AudioFile("rpg.wav")
while User.is_alive() and User.win == 0:
if __name__=='__main__':
p1 = Process(target = a.play)
p1.start()
p2 = Process(target = c)
p2.start()
p1.join()
p2.join()
game()
Shouldn't this allow a.play() and class c() to run at the same time?
Thanks for any feedback and answers!
Pleae try following code,
while User.is_alive() and User.win == 0:
if __name__=='__main__':
procs = [Process(target = a.play), Process(target = c)]
[p.start() for p in procs]
[p.join() for p in procs]

Multiprocessing beside a main loop

I'm struggling with a issue for some time now.
I'm building a little script which uses a main loop. This is a process that needs some attention from the users. The user responds on the steps and than some magic happens with use of some functions
Beside this I want to spawn another process which monitors the computer system for some specific events like pressing specif keys. If these events occur then it will launch the same functions as when the user gives in the right values.
So I need to make two processes:
-The main loop (which allows user interaction)
-The background "event scanner", which searches for specific events and then reacts on it.
I try this by launching a main loop and a daemon multiprocessing process. The problem is that when I launch the background process it starts, but after that I does not launch the main loop.
I simplified everything a little to make it more clear:
import multiprocessing, sys, time
def main_loop():
while 1:
input = input('What kind of food do you like?')
print(input)
def test():
while 1:
time.sleep(1)
print('this should run in the background')
if __name__ == '__main__':
try:
print('hello!')
mProcess = multiprocessing.Process(target=test())
mProcess.daemon = True
mProcess.start()
#after starting main loop does not start while it prints out the test loop fine.
main_loop()
except:
sys.exit(0)
You should do
mProcess = multiprocessing.Process(target=test)
instead of
mProcess = multiprocessing.Process(target=test())
Your code actually calls test in the parent process, and that call never returns.
You can use the locking synchronization to have a better control over your program's flow. Curiously, the input function raise an EOF error, but I'm sure you can find a workaround.
import multiprocessing, sys, time
def main_loop(l):
time.sleep(4)
l.acquire()
# raise an EOFError, I don't know why .
#_input = input('What kind of food do you like?')
print(" raw input at 4 sec ")
l.release()
return
def test(l):
i=0
while i<8:
time.sleep(1)
l.acquire()
print('this should run in the background : ', i+1, 'sec')
l.release()
i+=1
return
if __name__ == '__main__':
lock = multiprocessing.Lock()
#try:
print('hello!')
mProcess = multiprocessing.Process(target=test, args = (lock, ) ).start()
inputProcess = multiprocessing.Process(target=main_loop, args = (lock,)).start()
#except:
#sys.exit(0)

Categories

Resources