In Python, How to Put a Thread to Sleep Until a Specific Time

In Python, how can I put a thread to sleep until a specific time?

Here's a half-ass solution that doesn't account for clock jitter or adjustment of the clock. See comments for ways to get rid of that.

import time
import datetime

# if for some reason this script is still running
# after a year, we'll stop after 365 days
for i in xrange(0,365):
# sleep until 2AM
t = datetime.datetime.today()
future = datetime.datetime(t.year,t.month,t.day,2,0)
if t.hour >= 2:
future += datetime.timedelta(days=1)
time.sleep((future-t).total_seconds())

# do 2AM stuff

How to sleep until a specific time YYYY-MM-DD HH:MM:SS?

Easy, calculate how long it is, and sleep the time.

You can calculate how long it takes until your wakeup time is reached and sleep for the delta time.

Python can calculate with time intervals. If you subtract one timestamp from another, then you get a datetime.timedelta:

import datetime
import time

target = datetime.datetime(2019,1,20,12,0,0)

now = datetime.datetime.now()
delta = target - now
if delta > datetime.timedelta(0):
print('will sleep: %s' % delta)
time.sleep(delta.total_seconds())
print('just woke up')

of course, you can put that in a function:

import datetime
import time

target = datetime.datetime(2019,1,20,12,0,0)

def sleep_until(target):
now = datetime.datetime.now()
delta = target - now

if delta > datetime.timedelta(0):
time.sleep(delta.total_seconds())
return True

sleep_until(target)

You can check the return value: only if it slept, it returns True.

BTW: it's OK, to use a date in the past as target. This will generate a negative number of seconds. Sleeping a negative value will just not sleep.

if your time is a string, use this:

target = datetime.datetime.strptime('20.1.2019 20:00:00', '%d.%m.%Y %H:%M:%s')

or

target = datetime.datetime.strptime('2019-1-20 20:00:00', '%Y-%m-%d %H:%M:%s')

Python Sleep Until a Certain Time

Solution with a sleep-wait loop:

import datetime
import time

target_time = datetime.datetime(2017, 3, 7, 3) # 3 am on 3 July 2017
while datetime.datetime.now() < target_time:
time.sleep(10)
print('It is 3am, now running the rest of the code')

If instead of sleeping, you want to do other work, consider using threading.Timer or the sched module.

Sleeping a Thread until certain time in Python

Don't use thread sleeping. This is absolutely the wrong approach to the problem. If you don't want to use crons (I assume you mean literal linux cron jobs), use something like this https://docs.python.org/2/library/sched.html

Sleep until a certain amount of time has passed

It sounds like don't want to sleep for 30 second but rather pad the time it takes to perform an activity with a sleep so that it always takes 30 seconds.

import time
from datetime import datetime, timedelta

wait_until_time = datetime.utcnow() + timedelta(seconds=30)
move_motor()
seconds_to_sleep = (wait_until_time - datetime.utcnow()).total_seconds()
time.sleep(seconds_to_sleep)

if you are going to be doing this in multiple places you can create a decorator that you can apply to any function

import functools
import time
from datetime import datetime, timedelta

def minimum_execution_time(seconds=30)
def middle(func)
@functools.wraps(func)
def wrapper(*args, **kwargs):
wait_until_time = datetime.utcnow() + timedelta(seconds=seconds)
result = func(*args, **kwargs)
seconds_to_sleep = (wait_until_time - datetime.utcnow()).total_seconds()
time.sleep(seconds_to_sleep)
return result
return wrapper

You can then use this like so

@minimum_execution_time(seconds=30)
def move_motor(...)
# Do your stuff

time.sleep -- sleeps thread or process?

It blocks the thread. If you look in Modules/timemodule.c in the Python source, you'll see that in the call to floatsleep(), the substantive part of the sleep operation is wrapped in a Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS block, allowing other threads to continue to execute while the current one sleeps. You can also test this with a simple python program:

import time
from threading import Thread

class worker(Thread):
def run(self):
for x in xrange(0,11):
print x
time.sleep(1)

class waiter(Thread):
def run(self):
for x in xrange(100,103):
print x
time.sleep(5)

def run():
worker().start()
waiter().start()

Which will print:

>>> thread_test.run()
0
100
>>> 1
2
3
4
5
101
6
7
8
9
10
102

delay a task until certain time

Think you can also use the following code:

from datetime import datetime, time
from time import sleep

def act(x):
return x+10

def wait_start(runTime, action):
startTime = time(*(map(int, runTime.split(':'))))
while startTime > datetime.today().time(): # you can add here any additional variable to break loop if necessary
sleep(1)# you can change 1 sec interval to any other
return action

wait_start('15:20', lambda: act(100))

Dynamic time sleep until new minute starts with HH:MM:01 second

You can sleep the necessary amount of remaining time up to a minute by marking the time when the work starts and finishes, e.g.

import time
import random

while True:
start_time = time.time()
time.sleep(random.randint(2,5)) # do some work
worked_time = time.time() - start_time
print("worked for", worked_time)
wait_to_align = 60.0 - worked_time % 60.0
print(f"sleep {wait_to_align} to align to a minute")
time.sleep(wait_to_align)

produces

worked for 3.002328634262085
sleep 56.997671365737915 to align to a minute
worked for 5.003056764602661
sleep 54.99694323539734 to align to a minute
...


Related Topics



Leave a reply



Submit