Parallel multiprocessing in python easy example - python

I need to say that multiprocessing is something new to me. I read some about it but it makes me more confused. I want to understand it on a simple example. Let's assume that we have 2 functions in first one I just increment 'a' variable and then assign it to 'number' variable, in second I start first function and each every one second I want to print 'number' variable. It should looks like:
global number
def what_number():
a=1
while True:
a+=1
number=a
def read_number():
while True:
--> #here I need to start 'what_number' function <--
time.sleep(1)
print(number)
if __name__ == "__main__":
read_number()
How can I do that? Is there an easy and proper way to do that ?
UPDATE:
I saw noxdafox answer I'm really thankfull but it isn't exactly what I want. First of all I don't want send value in first function ('main' in noxdafox code). Second I don't want to get all values so quene will won't work. I need to get after each second number of while loops. Code should be something like :
import multiprocessing
import time
number = 0
def child_process():
global number
while True:
number += 1
print(number)
def main():
process = multiprocessing.Process(target=child_process)
process.start()
while True:
print("should get same number:",number)
time.sleep(0.001)
if __name__ == "__main__":
main()
If u run above code you get something like:
but this blue selected values should be same ! and that's the main problem :)
P.S sorry for chaos

Ok it takes some time but I figured it out. All it was about Sharing state between processes now all it works like charm. Code :
from multiprocessing import Process, Value
import time
def child_process(number):
number.value = 0
while True:
number.value += 1
#print(number)
def main():
num = Value('i')
process = Process(target=child_process, args=(num,))
process.start()
while True:
print("should get same number:", num.value)
time.sleep(1)
if __name__ == "__main__":
main()

As processes live in separate memory address spaces, you cannot share variables. Moreover, you are using global variables incorrectly. Here you can see an example on how to use global variables.
The most straightforward way to share information between processes is via a Pipe or Queue.
import multiprocessing
def child_process(queue):
while True:
number = queue.get()
number += 1
queue.put(number)
def main():
number = 0
queue = multiprocessing.Queue()
process = multiprocessing.Process(target=child_process, args=[queue])
process.start()
while True:
print("Sending %d" % number)
queue.put(number)
number = queue.get()
print("Received %d" % number)
time.sleep(1)
if __name__ == "__main__":
main()

Related

How do i do some stuff and count time in parallel in python?

I want my code to take some integers for some time (e.g. 10 seconds) and to count and print time every second. So it prints time permanently and i enter some numbers whenever i want. Maybe i should use async functions?
def accepting_bets():
global list_of_bets
list_of_bets = []
list_of_bets.append(int(input()))
def main():
i = 10
while True:
print(f"{i} seconds remaining...")
time.sleep(1)
i -= 1
accepting_bets()
if i == 0:
break
print(list_of_bets)
You can move the timing code to a different thread.
I would recommend researching about multi-threading in Python if you aren't aware about it.
import threading
import time
def countTime():
i = 10
while True:
print(f"{i} seconds remaining...")
time.sleep(1)
i -= 1
if i == 0:
break
print(list_of_bets)
thread1 = threading.Thread(target=countTime)
thread1.start()
# while you want to get the input
global list_of_bets
list_of_bets = []
list_of_bets.append(int(input()))
The countTime function will keep on running on another thread, and will not be paused by the input statement

Running two function together with multiprocessing and share variables

i used multiprocessing but i don't know how to do it
the logic : a variable sign is equal to 0, with a function called timer count 20 seconds and each second check if sign is equal to 1 then it'll print something and breaks the loop, at the same time with a function called waiting waits for an input from another library as example "discord" or "socket" so if the input is equal to my key flip the variable sign to 1 and that affects the first function timer
import multiprocessing
from time import sleep
sign = 0
def timer():
for s in range(20):
if sign == 1: # if the input is equal to the secret key then break the timer
print("Yes!")
break
else:
sleep(1) #if not then continue timing
def waiting():
# maybe it waits for an input or a message from "discord or whatsapp"
if message == "secret_key":
sign = 1
p1 = multiprocessing.Process(target=timer)
p2 = multiprocessing.Process(target=waiting)
p1.start()
p2.start()
I mentioned it above in a comment, but here is how you would use an event
import time
import multiprocessing as mp
def timer(exit_event):
for s in range(20):
if exit_event.is_set():
print("Yes!")
break
else:
time.sleep(1) #if not then continue timing
def waiting(exit_event):
# maybe it waits for an input or a message from "discord or whatsapp"
time.sleep(5)
exit_event.set()
if __name__ == '__main__':
exit_event = mp.Event()
p1 = mp.Process(target=timer, args=(exit_event,))
p2 = mp.Process(target=waiting, args=(exit_event,))
p1.start()
p2.start()
p1.join()
p2.join()
However the real way to use an Event is to just to wait() for it to become true. No need for a sleep loop.
def timer(exit_event):
if exit_event.wait(timeout=20)
# returns True if the event is True. False if timed out
print("Yes!")

Is there anyway to wait for a couple of minutes and if no input is provided then take the value "n" as input for first variable?

while 1:
wat=water()
if wat==10:
print("water condition")
mixer.music.load("water.mp3")
mixer.music.play()
first=input("Drank?Y/N")
if first.lower()=="y":
with open("HealthLog.txt","a") as water1:
Content=f"Drank water at [{getdate()}] \n"
water1.write(Content)
else:
pass
Is there any way to wait for a couple of minutes and if no input is provided, then take the value "n" as input for the first variable?
Guess by default it will wait indefinitely. I tried using a timer function, but it cannot record any input.
What I am trying to do is to track my activities, so if I drink water I say y--> this records my activity and writes it to a file.
All help will be greatly appreciated
Here is how you can use a combination of pyautogui.typewrite, threading.Thread and time.sleep:
from pyautogui import typewrite
from threading import Thread
from time import sleep
a = ''
def t():
sleep(5)
if not a: # If by 5 seconds a still equals to '', as in, the user haven't overwritten the original yet
typewrite('n')
typewrite(['enter'])
T = Thread(target=t)
T.start()
a = input()
b = input() # Test it on b, nothing will happen
Here is the code implemented into your code:
from pyautogui import typewrite
from threading import Thread
from time import sleep
while 1:
wat = water()
if wat == 10:
print("water condition")
mixer.music.load("water.mp3")
mixer.music.play()
first = 'waiting...'
def t():
sleep(5)
if first == 'waiting...':
typewrite('n')
typewrite(['enter'])
T = Thread(target=t)
T.start()
first = input("Drank?Y/N")
if first.lower() == "y":
with open("HealthLog.txt","a") as water1:
Content=f"Drank water at [{getdate()}] \n"
water1.write(Content)
else:
pass

input() function throwing error in presence of threading in python

Following code works as expected. It takes two inputs and outputs the same
import sys
import threading
def main():
n = int(input("input n:"))
parents = list(map(int, input("input parents:").split()))
print("n is {0} and parents is {1}".format(n,str(parents)))
if __name__ == "__main__":
main()
The moment I add this additional code for enabling more depth for recursion and threading, it throws a value error. Inputs I give are '3' for the first input (without quotes) and '-1 0 1' for the second input (without quotes).
import sys
import threading
def main():
n = int(input("input n:"))
parents = list(map(int, input("input parents:").split()))
print("n is {0} and parents is {1}".format(n,str(parents)))
sys.setrecursionlimit(10**7) # max depth of recursion
threading.stack_size(2**27) # new thread will get stack of such size
threading.Thread(target=main).start()
if __name__ == "__main__":
main()
The main() function is called from two places.
First, From the thread main() function will be called
threading.Thread(target=main).start()
Second, the __main__ will be called. So here also the main() function is called.
if __name__ == "__main__":
main()
So you were asked to enter the "input n" two times. While entering the string value ('-1 0 1') the second time, you are giving value to the "input n" again. It's expecting int as input. So the issue is happening.
Code Fix:
Move the thread inside main and remove the existing main()
import sys
import threading
def main():
n = int(input("input n:"))
parents = list(map(int, input("input parents:").split()))
print("n is {0} and parents is {1}".format(n, str(parents)))
if __name__ == "__main__":
sys.setrecursionlimit(10 ** 7) # max depth of recursion
threading.stack_size(2 ** 27) # new thread will get stack of such size
threading.Thread(target=main).start()
I hope it'll help you...

How can i stop timer code

def data():
a=0
a+=1
print(a)
#if a==5:
#sys.exit()
b=threading.Timer(3, data)
b.start()
if __name__ == "__main__":
data()
①I want to try stop this code about 15 seconds
(Actually,I need to stop the time is about 16200 second, and it's must be very precise )
(i want to know is there a better timer code?)
i have tried many times to make i to be 5,but i don't know how to do
a will be zero everytime.
I'm not sure what the multithreading is about, but if you just want the code to stop in ~15 seconds, I would try this:
import time
import sys
def data():
start = time.time()
while (start-time.time()<=15):
#code
sys.exit()
I don't know what the i is, or what it's keeping track of, but this should work!
About stopping the code for 15 seconds, Why don't just use time.sleep() and about exit the sys.exit() will do the trick like:
import time
import sys
def data():
a=0
a+=1
print(a)
time.sleep(15) #stop the code for 15 seconds
if a==5:
sys.exit()

Categories