time.sleep(N) attempts to sleep at least N seconds of elapsed, AKA "wall-clock" time - of course there can be no guarantee that the sleep will last exactly N seconds; for example, the thread becomes ready to execute again at that time, but it cannot necessarily preempt whatever other thread is executing at that time -- that's the operating system's decision to make, not any programming language's; on the other hand, sleep may be prematurely interrupted by various kinds of events (such as interrupts).
If you can find on your operating system some clock-like thingy that only advances when the system's state is the one you care about (e.g. "not hybernated", in your case), then of course you can go back to sleep if you wake up again "too early".
For example, on Windows 7, QueryUnbiasedInterruptTime is specifically documented to "not include time the system spends in sleep or hibernation" and to use units of 100 nanoseconds. So if you call that, e.g. through ctypes, you can achieve the effect you want:
def unbiasedsleep(n):
start = kernel32.QueryUnbiasedInterruptTime()
target = start + n * 10 * 1000 * 1000
while True:
timeleft = target - kernel32.QueryUnbiasedInterruptTime()
if timeleft > 0:
time.sleep(timeleft / (10 * 1000 * 1000.0))
I don't know how to get the equivalent of QueryUnbiasedInterruptTime on other releases of Windows or other operating systems, but then, you don't tell us what operating system(s) you're interested in, so it would be pretty pointless anyway to present a long laundry lists of approaches which may work similarly in different environments.