I want to be able to be able to run a function at a random time as long as the program is running.
Let's say I have this function:
def sample_func:
print("Function is running.")
and some other code running. As long as the program is being run, I want this function to run at a random amount of time between 5 to 10 minutes while other code is being run. Is this possible?
Here's the code you're looking. Set the sleep timer for 5-10 minutes.
Insert your main flow code inside the "main flow" function.
import random
import threading
import time
def random_function():
print("Function is running.")
def call_random_function():
while True:
time.sleep(random.randint(1, 5))
random_function()
def main_flow():
"""
Do your main flow here
"""
a = 1
while a < 10:
print(a)
a += 1
time.sleep(10)
if __name__ == '__main__':
threading.Thread(target=call_random_function).start()
main_flow()
print("Program is finished.")
Related
I am trying to make an attendance system and right now, I want to create a random password, and put it on a countdown so that as it runs out, the student can't use the code anymore. However, when I try to run it, it only displays the password and the countdown, and only asks for input after the timer runs out.
I have attempted to use a for loop as well as the multiprocessing module to no avail. I suspect that the error is located somewhere around my use of the threads.
import threading
#create code and timer
Thread1 = threading.Thread(target=generateCodeandTimer(600))
# make input
Thread2 = threading.Thread(target=attend)
# Start the thread
Thread1.start()
# Start the thread
Thread2.start()
But for reference, this is my full code:
import string
import random
import time
import sys
import threading
code = ""
def generateCodeandTimer(s):
global code
code = ''.join((random.choice(string.ascii_lowercase + string.digits) for x in range(6)))
print("Attendance code:", code)
while s != -1:
mins = s // 60
secs = s % 60
countdown = '{:02d}:{:02d}'.format(mins, secs)
sys.stdout.write('\r' + countdown)
time.sleep(1)
s -= 1
if s==-1:
print()
print("Code expired")
def attend():
print()
studentinput = input("Please enter the code")
if studentinput == code:
print()
print("Your attendance has been taken")
else:
print()
print("Wrong code!")
#create code and timer
Thread1 = threading.Thread(target=generateCodeandTimer(600))
# make input
Thread2 = threading.Thread(target=attend)
# Start the thread
Thread1.start()
# Start the thread
Thread2.start()
In this line:
Thread1 = threading.Thread(target=generateCodeandTimer(600))
you are actually calling the function generateCodeandTimer. The target keyword requires a function object, but this code calls the function and then passes the result as the target of the thread.
The second time you started a thread, you got it right:
Thread2 = threading.Thread(target=attend)
Note the difference: target=attend passes the function object attend because you do not CALL the function. If you had written target=attend(), you would have called the function and passed its result as the target.
The solution is found in the documentation for the Thread constructor. Change the first thread creation to this:
Thread1 = threading.Thread(target=generateCodeandTimer, args=(600,))
The comma after 600 is necessary because the args= keyword requires a tuple.
Your program will now run as you intend. You will discover some other problems - for example, the program won't exit immediately when the user types in the password. But I will let you figure those out, or ask more questions if you run into trouble.
I want to execute a task after certain time, so I have tried a countdown timer with a condition of being finished (when countdown variable = 0, the task is performed). The thing is that I don't want to stop the execution of the main program while performing the countdown. I have tried this:
import time
def countdown(num_of_secs):
while(num_of_secs):
time.sleep(1)
num_of_secs -= 1
return num_of_secs
So, I run my code setting a number of seconds to the countdown, and when this countdown reaches the 0 value, a task must be executed. Using this code (it uses a while), when I call my function "countdown" it stops the execution of the main program, so it is the same as a big time.sleep. I want to carry out this countdown in the background, without stopping other actions until the countdown finishes and the task starts.
Thank you
Another alternative is by using threading.
I've got a simple example here with 2 Threads where the working thread is waiting for the countdown thread to finish and starting. The Main is still working fine.
import threading
import time
def do_something():
countdown_thread.join()
print("Starting Task")
time.sleep(3)
print("Finished Task")
def countdown(num_of_secs):
while(num_of_secs):
time.sleep(1)
num_of_secs -= 1
print(num_of_secs)
if __name__ == '__main__':
countdown_thread = threading.Thread(target=countdown, args=(3,))
work_thread = threading.Thread(target=do_something)
countdown_thread.start()
work_thread.start()
while True:
print("Main doing something")
time.sleep(1)
Example picture for multithreading: Sequential vs Threading
Usually python only has a single program flow, so every instruction needs to complete before the next one can get executed.
For your case you need asynchronicity, with e.g. asyncio.sleep(5) as a separate task in the same event loop.
import asyncio
async def sleeper():
print('Holding...')
await asyncio.sleep(5)
print('Doing Work!')
async def work():
print('Doing work')
print('while')
print('the other guy is sleeping')
async def main():
await asyncio.gather(sleeper(), work())
asyncio.run(main())
The most common and easiest way to implement this would be with a Timer object from the threading library. It would go as follows:
import threading
import time
i = 0
done = False
def show_results():
print("results from GPIO readings")
print("=)")
global done
done = True # signal end of while loop
def read_GPIO():
print("reading GPIO...")
t = threading.Timer(60, show_results) # task will trigger after 60 seconds
t.start()
# your while loop would go here
read_GPIO() # do work
while not done:
print("waiting", i) # doing work while waiting for timer
time.sleep(1)
i += 1
pass
Notice that the time library is used only for illustrative purposes. You could also start the timer recursively to check periodically GPIOs and print results or trigger an event. For more information on the threading library or the Timer object check the docs
I wrote proxy checker and I need to automate checking for every 5 minutes. My while True loop skips the functions. When I have first iteration - functions are running, but with next iterations they are skipped, just printing START!!!!!! and END---- in my console.
if __name__ == "__main__":
while True:
print("START!!!!!!!!!!")
http_proxy_check()
save_proxy('http')
print("END------------------")
time.sleep(2)
http_proxy_check function:
def http_proxy_check():
for proxy in http_proxyList:
print(f"Checking {http_proxyList.index(proxy)} of {len(http_proxyList)} element")
thread = Thread(target=checkIp_http,args=(proxy.strip(), ))
if len(threads)<=1200 :
thread.start()
threads.append(thread)
else:
threads.clear()
for thread in threads:
thread.join()
You are directly trying to run subthreads. Why are you not using multiprocess?
Also you can try to "timeloop" library for periodic tasks;
https://pypi.org/project/timeloop/
pip install timeloop
import time
from timeloop import Timeloop
from datetime import timedelta
tl = Timeloop()
#tl.job(interval=timedelta(minutes=5))
def sample_job_every_5m():
print "5m job current time : {}".format(time.ctime())
while True: # infinite loop
your_code_that_process() # put your code that do stuff once and exit
time.sleep(5*60) # 300 seconds of sleeping, make it wait 300sec
if check_for_abort_if_so_break(): # you can make flag that you trigger on error or by input
# so you can exit out of infinite loop
break # exit infinite loop (not so infinite anymore)
I want to execute FUNCTION periodically every 60 seconds, but I don't want to execute FUNCTION again IF the previous run has not completed yet. If the previous run completes in e.g. 120s then I want to execute a new FUNCTION call straight away. If previous run completed in e.g. 10s then I want to wait 50s before I execute a new FUNCTION call.
Please see my implementation below.
Can I achieve it with e.g. subprocess.run or some timeloop library so that the implementation would be much cleaner?
import time
def hello(x):
# some logic here
# execution could take any time between e.g. <10s, 120s>
def main(ii):
while True:
start = int(time.time())
try:
val = next(ii)
except StopIteration as ex:
return None
else:
hello(val)
run_time_diff = int(time.time()) - start
if run_time_diff < 60:
time.sleep(60 - run_time_diff)
ii = iter(list[[...],[...],...[...]])
main(ii=ii)
maybe apsheduler could help you. But if your job wil run more then waiting time, it could be skipped. In this case you can increase number of workers.
import datetime
import time
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
def some_job():
time.sleep(5)
print(f"{datetime.datetime.utcnow()}: Every 10 seconds")
job = scheduler.add_job(some_job, 'interval', seconds=10, max_instances=1)
scheduler.start()
try:
while True:
time.sleep(1)
finally:
scheduler.shutdown()
I have two python scripts as separate file. say for example hello.py and hello1.py. lets take my total execution time is 100 seconds. So i want hello.py to execute for first 60 sec and hello1.py to execute for 40 secs. So how to spilt it and do?
You can use alarms to interrupt code after it has been running for a while. The advantage is that the code being run need not be aware of the time limits. The downside is that it has no chance to terminate gracefully (although you could catch the Stop exception to do so).
import signal
import time
def task(name):
"""Generic task -- print out name once a second."""
while True:
print(name)
time.sleep(1)
class Stop(Exception):
"""Raised to stop a running task."""
pass
def onAlarm(signum, frame):
"""Alarm signal handler."""
raise Stop
def run(function, seconds):
"""Run a function for a specified number of seconds."""
# install our alarm handler
savedHandler = signal.signal(signal.SIGALRM, onAlarm)
# request an alarm after the specified numbers of seconds
signal.setitimer(signal.ITIMER_REAL, seconds)
# run the function
try:
function()
except Stop:
pass
# restore the saved timeout handler
signal.signal(signal.SIGALRM, savedHandler)
# run hello for 6 seconds
run(lambda: task("hello"), 6)
# run hello1 for 4 seconds
run(lambda: task("hello1"), 4)
Let me define two python scripts, temp4.py and temp5.py. Contents:
temp4.py
def f1():
print 'hello'
temp5.py
def f2():
print 'hello1'
a final script temp5.py. this will measure time and run the scripts accordingly. change the times. here, both scripts will run for 10 seconds.
from temp4 import f1
from temp5 import f2
from timeit import default_timer as timer
start = timer()
while (timer()-start)<10:
f1()
print timer()-start
while (timer()-start)<20: #add timings here
f2()
print timer()-start
Please add the second time to the timer. So the first time will be 60, second will be 100.