i would like to know how i let my program to check the if-statement all the time while the others functions still running.
def back():
print("back")
counter = 0
while counter <= 1:
if statement == True:
print("hey")
counter += 1
back()
Here the statement has to be True before the function back can be executed, but I want it all at the same time to run
Is this what you're looking for? This will trigger back() to run in the background every time statement is True and it will store a reference to the background process in background_processes
import multiprocessing
def back():
print("back")
counter = 0
background_processes = []
while counter <= 1:
if statement == True:
print("hey")
p1 = multiprocessing.Process(target=back)
p1.start() # back() will run in the background and this loop will keep going
background_processes.append(p1)
counter += 1
Related
So I wrote this script, which counts income packets on certain port, and in case if there are to many packets script has to do something. On the first received packet is has to start timer, and if timer reaches 60 sec, packet count should start from 0 again. It works, but only for first timer call, in any case, if script has to start timer again I get the error:
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once"`
It's clear, that this thread still running, but i don't understand why. I mean, in case if timer reaches 60 secs, timer loop is finished, and function should be finished too, so i can use timer again? Clearly i don't understand something here, can you guys explain it? Thanks for answers
My code:
from scapy.all import *
from threading import Thread
import time
global count
count = 0
def timer():
global count
i = 0
while i < 60:
if count > 0:
time.sleep(1)
i = i + 1
print(str(count))
else:
print("count is 0, timer turning off...")
break
else:
count = 0
print("60 seconds, timer is off")
background_thread = Thread(target=timer)
def pkt_callback(pkt):
global count
packet_limit = 10
if pkt.haslayer(UDP) and pkt.getlayer(UDP).dport == 5160 and pkt.haslayer(Raw):
raw = pkt.getlayer(Raw).load
s = str(raw)
if 'REGISTER' in s:
count += 1
print(count)
if count == 1:
if background_thread.is_alive() is False:
background_thread.start()
print("Register packet detected, timer is on")
if count >= packet_limit:
print("PACKETLIMIT reached, do smth")
count = 0
sniff(iface='ens160', filter="", prn=pkt_callback)
I think you have to use the return function not break, and either way you have only used it once, also you can change your code a bit, try this:
def timer():
global count
i = 0
while i < 60:
if count != 0:
time.sleep(1)
i += 1
print(str(count))
else:
return "count is 0, timer turning off..."
else:
count = 0
return "60 seconds, timer is off"
I am building a tkinter GUI program which has two loops running together. People have kindly helped me with making "Start" and "Stop" buttons for it (see Creating Tkinter buttons to stop/skip a 2D loop [Solved]). However, a new problem came. In the following code, all the buttons are functioning as we expected. But the speed of the cycling is wrong.
The program is designed to print once per second. However, after finishing printing the first Row, the program starts to print twice per second. I tried a lot but cannot find the reason for that. Can anyone help. Thanks in advance!
import tkinter as tk
root = tk.Tk()
scan_array = [1,"two",3,"ten"]
running = True
Hor_index = 0
Hor_end = 7
Ver_index = 0
def Hor_scan():
global Hor_index, running, dont_run
if (Hor_index > Hor_end) and (Ver_index > len(scan_array)):
running = False
elif (Hor_index < Hor_end):
Hor_index += 1
print ("Row " + str(scan_array[Ver_index-1]) + " Column: " + str(Hor_index))
else:
running = False
Ver_scan()
if (running):
root.after (1000, Hor_scan)
def Ver_scan():
global Ver_index, Hor_index, running
if Ver_index < len(scan_array):
Hor_index = 0
Ver_index += 1
running = True
Hor_scan()
def start():
global Ver_index, Hor_index, running
Ver_index = 0
Hor_index = 0
running = True
print ("A new run started")
Ver_scan()
def skip():
global Ver_index, Hor_index
Ver_index += 1
Hor_index = 0
def stop():
global running
running = False
btnStart = tk.Button(root,text="Start",command=start)
btnSkip = tk.Button(root,text="Skip",command=skip)
btnStop = tk.Button(root,text="Stop",command=stop)
btnStart.grid()
btnSkip.grid()
btnStop.grid()
root.mainloop()
I don't see the point of having an extra if (running): statement in Hor_scan, because this
elif (Hor_index < Hor_end):
condition will anyway be only performed if it is "running". You can make the following changes
def Hor_scan():
global Hor_index, running, dont_run
if (Hor_index > Hor_end) and (Ver_index > len(scan_array)):
running = False
elif (Hor_index < Hor_end):
Hor_index += 1
print ("Row " + str(scan_array[Ver_index-1]) + " Column: " + str(Hor_index))
root.after (1000, Hor_scan)
else:
running = False
Ver_scan()
REASON : If you you call root.after from the condition as you were doing previously, you will end up scheduling one extra call per cycle, because running does not become False right after you are done with the cycle, it initiates another one, only then your program executes else which actually makes running False.
The goal of this script is to make a switch and let the user toggle it ON and OFF with a key press, and when the switch is ON, the script should execute a loop that print a message in the terminal. In another words, The goal is to repeatedly print a message when the switch is ON
Here is what i have tried:
import keyboard
import time
switch = 0 # The switch variable
def check_start():
global start
if keyboard.is_pressed("F5") and start == 0: # If F5 is pressed, turn ON print message loop
switch = 1
print(switch)
time.sleep(0.1) # This is to prevent the user toggling the switch too fast
if keyboard.is_pressed("F5") and start == 1: # If F5 is pressed again, turn OFF print message loop
switch = 0
print(switch)
time.sleep(0.1)
def print_name(): # If the switch is ON, it should print two seperate message with a 10 seconds interval
if start == 1:
print("start")
time.sleep(10)
print("end")
while True:
check_start()
print_name()
Here is the output of the script:
1
start
end
start
end
0
1
start
end
0
Now here's the problem:
The user cannot turn off the switch while the print loop is in progress. For example the user cannot turn off the script if the message "end" has not printed, the user can ONLY turn off the switch exactly after "end" has printed, and if the user has missed the opportunity to turn off the switch, he must wait 10 more seconds to turn it off. What i expected is the user can toggle On and OFF anytime s/he wishes to.
Is this possible to do in without importing too much module?
you can put an if condition inside your loop to do a break at a specific key
ex:
if keyboard.is_pressed("F5") and start == 1:
break
this would exit your infinite loop, although a more elegant code would work like this:
def check_start():
global start
if keyboard.is_pressed("F5") and start == 0:
#DO stuff
return True
if keyboard.is_pressed("F5") and start == 1:
#DO stuff
return False
while check_start():
print_name()
Here is a cleaner, more reliable approach using keyboard's built-in add_hotkey method.
Below is a simple program to toggle printing of the current timestamp.
import keyboard as kb
from datetime import datetime as dt
global print_flag
print_flag = False
def toggle_print():
global print_flag
print_flag = not print_flag
kb.add_hotkey('d', toggle_print)
while True:
timestamp = dt.now()
if print_flag:
print(timestamp)
everything works except the next song doesn't play after the first is finished.
import os, random
from pygame import mixer
from pynput import keyboard
startup = 0
pause = 0
volume = 0.5
def Picker():
global startup
global volume
startup += 1
if startup > 1:
ThisSong = random.choice(os.listdir("C:\\Users\\...\\Music"))
NextSong = random.choice(os.listdir("C:\\Users\\...\\Music"))
ThisSong = NextSong
if ThisSong != NextSong:
mixer.init()
mixer.music.load("C:\\Users\\...\\Music" + ThisSong)
mixer.music.play(0)
mixer.music.set_volume(volume)
while mixer.music.get_busy():
def on_press(key):
global pause
global volume
if key == keyboard.KeyCode(char='-'):
volume -= 0.1
if volume < 0.1:
volume = 0.1
mixer.music.set_volume(volume)
if key == keyboard.KeyCode(char='='):
volume += 0.1
if volume > 1:
volume = 1
mixer.music.set_volume(volume)
if key == keyboard.KeyCode(char='['):
pause += 1
if pause == 1:
mixer.music.pause()
pause = 2
if pause == 3:
mixer.music.unpause()
pause = 0
with keyboard.Listener(on_press=on_press) as listener: listener.join()
else:
Picker()
else:
pass
Picker()
Picker()
screenshot of code
I can't get it to work, i'm very new to python so i'm probably missing something
obvious
Before starting: Thx #JGreenwell for copying the code.
Ok, so first, I’ll help you clean your code.
Things that are wrong
Having all that ThisSong and NextSong things: It won’t get saved when you restart Picker(). Either just have ThisSong, or place the ThisSong and NextSong assignment with the volume and pause variables:
.
pause = 0 # this is a problem! Next point
volume = 0.5
ThisSong = random.choice(...)
NextSong = random.choice(...)
The pause variable should be a boolean (True/False) and the pausing code should be like this:
.
pause = not pause
if pause:
# pause
else:
# unpause
Also, it would ideally be called paused
on_press and the Listener declaration should be outside the while loop, because otherwise they just keep being declared every time it loops. Then you should import time and put time.sleep(500) or something like that in the while loop, so that it doesn’t check every fraction of second.
As for the next song not playing, I don’t really know, but I’d suggest entering Picker() in the shell after the program has run (python -i script.py from CMD, IDLE leaves you in a shell by default). I would also suggest really following recommendation #3 as having them in the loop may break the loop and stop it from finishing. Most importantly, I would ask you to debug your code by adding print in every step of your code:
print(1)
if something:
print(2)
etc...
And seeing where it blocks
P.S.: The random dots are because you can’t have code in lists, so I had to exit the list.
Working solution, incase anyone else has the same problem as me in the future :)
from pygame import mixer
from pynput import keyboard
import threading
import random
import os
paused = 0
def player():
song = random.choice(os.listdir("C:\\users\\...\\desktop\\music"))
mixer.init()
mixer.music.load("C:\\users\\...\\desktop\\music\\" + song)
mixer.music.play(0)
while mixer.music.get_busy():
pass
else:
player()
def main():
t = threading.Thread(target = player, name = 'thread1', args = ())
t.start()
main()
def on_press(key):
global paused
if key == keyboard.KeyCode(char='['):
paused = not paused
if paused:
mixer.music.pause()
else:
mixer.music.unpause()
with keyboard.Listener(on_press=on_press) as listener: listener.join()
I am trying to make a text based game in which the user is a pilot in space. I want to create a movement system but am unsure how to do it. I want the user to be able to put in the desired grid coordinates, and his vehicle will begin to change its grid coords to get closer and closer to the ones he inputted.
Now, to do this I will probably need multithreading and a time element. But I am unsure how I can use a time element. Any advice is greatly appreciate, i'm just trying to learn here. Thanks guys!
from Gundam2 import Mobilesuits
#Main Variable/Object declarations:
Leo1=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,100,100])
Leo2=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[300,100,100])
Leo3=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,150,100])
currentmobilesuit=Leo1
#Main Function declarations
def commands(user_input,currentmobilesuit):
if user_input == "radar":
currentmobilesuit.radar()
elif user_input == "commands":
print("Command list:\nradar")
else:
print("Invalid command\nType 'commands' for a list of valid commands")
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
class Mobilesuits:
#class global variables/methods here
instances = [] #grid cords here
def __init__(self,armor,speed,name,description,cockpit_description,\
radar_range, coordinates):
Mobilesuits.instances.append(self)
self.armor=armor
self.speed=speed
self.name=name
self.description=description
self.cockpit_description=cockpit_description
self.radar_range=radar_range
self.coordinates=coordinates
def can_detect(self, other):
for own_coord, other_coord in zip(self.coordinates, other.coordinates):
if abs(own_coord - other_coord) > self.radar_range:
return False
return True
def radar(self):
for other in Mobilesuits.instances:
if other is not self and self.can_detect(other):
print "%s detected at %s" % (other.description, other.coordinates)
Games typically have a "master loop" of some kind; yours does here:
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
The simplest thing to do is to count in the loop:
#Main execution
turn_count = 0
while True:
commands(raw_input(),currentmobilesuit)
turn_count += 1
If you wanted the real time taken to have some impact on the counter, or be the counter, you can get the current time from the time module calling time.time().
#Main execution
import time
time_start = time.time()
time_elapsed = 0
while True:
commands(raw_input(),currentmobilesuit)
time_elapsed = time.time() - time_start
A couple other thoughts:
Make a Game class, and put the turn counter and game loop in that.
Have the commands function return a number that is the number of time units that took place during the command; for example, entering an invalid command might take 0 turns, while repairing a robot might take 5.
#Main execution
turn_count = 0
while True:
turns_taken = commands(raw_input(),currentmobilesuit)
turn_count += turns_taken
You can use non-blocking I/O. This will help you avoid the complications of threading. Here's your sample code implemented with a non-blocking read of stdin:
#!/usr/bin/python
import sys
import select
call_count = 0
#Main Function declarations
def commands(user_input):
global call_count
if len(user_input) > 0:
print('call count: ' + str(call_count) + ' user entered: ' + user_input)
def raw_input_no_block():
global call_count
call_count = call_count + 1
input_avail = select.select([sys.stdin], [], [], 0.1)[0] #wait for 0.1 seconds
if input_avail:
return sys.stdin.readline()
else:
return ''
#Main execution
while True:
commands(raw_input_no_block())