I wrote this script a few days ago in VSCode. It's supposed to open my zoom meetings every day at a certain time and I really want it to work because it's one of my first projects. I think I wrote everything correctly, however. it won't work. Do you see what I'm missing?
import webbrowser
import schedule
import time
url_deutsch = "https://us04web.zoom.us/j/79379252675?pwd=cm1NUUlSMlg4aSsyWXVwL3UybzhOUT09"
url_chemie = 'https://zoom.us/j/95643744370?pwd=clRkMDNEVTZ3dzErZWUvZWZFVFVvQT09'
url_englisch = 'https://us02web.zoom.us/j/3470923893?pwd=ejdIaVdaL21yWXVPaU9wdnBDalhYUT09'
url_opv = 'https://us04web.zoom.us/j/79683686777?pwd=QXhmVTZFZitCbUowZTh1bDFTWjRVQT09'
url_test = 'google.com'
chrome_path = 'C:/Program Files/Google/Chrome/Application/chrome.exe %s'
#Zoom aleman
def open_link_deutsch():
webbrowser.get(chrome_path).open(url_deutsch)
return
#Zoom quimica
def open_link_chemie():
webbrowser.get(chrome_path).open(url_chemie)
return
#Zoom ingles
def open_link_englisch():
webbrowser.get(chrome_path).open(url_englisch)
return
def open_link_test():
webbrowser.get(chrome_path).open(url_test)
return
while True:
schedule.run_pending()
time.sleep(0)
#Schedule
schedule.every().monday.at('13:30').do(open_link_deutsch)
schedule.every().tuesday.at('11:00').do(open_link_deutsch)
schedule.every().wednesday.at('09:10').do(open_link_deutsch)
schedule.every().wednesday.at('07:15').do(open_link_chemie)
schedule.every().tuesday.at('07:15').do(open_link_englisch)
schedule.every().friday.at('09:10').do(open_link_englisch)
schedule.every().friday.at('12:51').do(open_link_test)
After you run this code, it will not wait for the events that you sheduled.
According to official schedule documentation on PyPI, you should add
import time
to imports and something like
while True:
schedule.run_pending()
time.sleep(1)
at the end of your code. This will execute forever and check if any event is pending for this exact moment every second.
You need to set the schedule before entering the while-loop. The code is doing something, it's checking to see if any jobs are scheduled, constantly. Move the schedule.every() calls before the loop, and choose a more reasonable time to wait between schedule polls. The code below polls about every 60s which I think is fine, but you could make it poll more frequently.
import schedule
import time
import webbrowser
#Zoom quimica
def open_link_chemie():
webbrowser.get(chrome_path).open(url_chemie)
return
#Zoom ingles
def open_link_englisch():
webbrowser.get(chrome_path).open(url_englisch)
return
def open_link_test():
webbrowser.get(chrome_path).open(url_test)
return
#Schedule
schedule.every().monday.at('13:30').do(open_link_deutsch)
schedule.every().tuesday.at('11:00').do(open_link_deutsch)
schedule.every().wednesday.at('09:10').do(open_link_deutsch)
schedule.every().wednesday.at('07:15').do(open_link_chemie)
schedule.every().tuesday.at('07:15').do(open_link_englisch)
schedule.every().friday.at('09:10').do(open_link_englisch)
schedule.every().friday.at('12:51').do(open_link_test)
while True:
schedule.run_pending()
time.sleep(60)
Related
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
import schedule
import time
def job(work):
print(work)
schedule.every().day.at("10:30").do(job(work))
while True:
schedule.run_pending()
time.sleep(1)
How to call job(work) inside my do() function. if i give job() it works fine, but if i give job(work) it throwing error. what to do with this? any help
This is in the schedule FAQ:
import schedule
import time
def job(work):
print(work)
schedule.every().day.at("10:30").do(job,work="") # make "" whatever string you want
while True:
schedule.run_pending()
time.sleep(1)
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 used the schedule library to schedule a function every X seconds:
Want I want is to run this function on separate thread. I found this in the documentation on how to Run the scheduler in a separate thread but I didn't understand what he did.
Is there someone who can explain to me how to do that ?
Update:
This what I tried:
def post_to_db_in_new_thread():
schedule.every(15).seconds.do(save_db)
t1 = threading.Thread(target=post_to_db_in_new_thread, args=[])
t1.start()
You don't really need to update schedule in every task
import threading
import time
import schedule
def run_threaded(job_func):
job_thread = threading.Thread(target=job_func)
job_thread.start()
schedule.every(15).seconds.do(run_threaded, save_db)
while 1:
schedule.run_pending()
time.sleep(1)
I have below code to download a file inside a loop,
import wget
try:
wget.download(url)
except:
pass
But if the Internet goes down, it doesn't return!
So my whole loop is stuck.
I want to repeat the same download if internet goes down. So I wanna know does any error happen.
How can i mitigate this?
One simple solution is to move your download code to a thread and make it a separate process which can be interrupted.
You can use python Thread and Timer module to achieve it.
from threading import Thread, Timer
from functools import partial
import time
import urllib
def check_connectivity(t):
try:
urllib.request.urlopen("http://google.com", timeout=2)
except Exception as e:
t._Thread__stop()
class Download(Thread):
def run(self):
print("Trying to download file....")
con = partial(check_connectivity, self)
while True:
t = Timer(5, con) # Checks the connectivity every 5 second or less.
t.start()
# your download code....
def main():
down = Download()
down.start()
down.join()
You code move your main download loop inside the thread's run method. And start a timer inside which listens for the network connectivity.