2

I just wrote a function that looked like this:

def block_for(seconds):
    """Wait at least seconds, this function should not be affected by the computer sleeping."""
    end_time = datetime.datetime.now() + datetime.timedelta(seconds)

    while datetime.datetime.now() < end_time:
        pass

Can anything bad come of this? Should there ideally be something inside the while loop?

theonlygusti
  • 11,032
  • 11
  • 64
  • 119
  • That should be completely fine, and is exactly the sort of case that `pass` is intended for. The only suggestion I would make here is that, at the top of your code, do `from datetime import datetime` and `from datetime import timedelta` and then change `datetime.datetime.now` to `datetime.now` and `datetime.timedelta`, That'll reduce your overhead a little by only importing the bits of `datetime` that you need _and_ make the code a little more readable. That is, unless you are using some other bit of `datetime` elsewhere in your code. – Chris Larson Jan 01 '17 at 12:00
  • The nice thing about using `pass` here is that your code is valid for python 2 and 3. The print statement in the Answer elsewhere using the trailing , and the `end=` syntax is only valid for python 3, and the python 2 syntax for the same effect won't run in python 3. – Chris Larson Jan 01 '17 at 12:02
  • The time.sleep(1) replacement answer works well, too, with perhaps a marginal improvement in cycles. – Chris Larson Jan 01 '17 at 12:21

2 Answers2

4

time.sleep(seconds) seconds does just that without burning through CPU cycles. your loop keeps the CPU fully busy. i do not know for you but i consider this bad.

hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
  • Maybe, but time.sleep gets interrupted by the computer sleeping, my loop would not. – theonlygusti Jan 01 '17 at 09:37
  • I am looking for a solution to http://stackoverflow.com/q/41411001/3310334, and my question poses one, and I want to know if it is safe – theonlygusti Jan 01 '17 at 09:38
  • 1
    you could still `sleep` inside your loop for say 1 sec; that would still be better - the loop would only run once every second. – hiro protagonist Jan 01 '17 at 09:39
  • not sure if that can be done; also [`Timer`](https://docs.python.org/3/library/threading.html#timer-objects) will probably be thrown off when you suspend your computer. timed execution is something operating systems are good at (`cron` or `at` or whatever your OS of choice offers). don't know if that is an option for you. – hiro protagonist Jan 01 '17 at 09:48
  • 2
    @theonlygusti I don't understand the issue with this proposed solution. You only substitute `pass` with `sleep` for a very short period of time. The idea is just that you don't have the CPU running through the `while` loop as fast as it can possibly go. The delay doesn't have to be significant. – roganjosh Jan 01 '17 at 09:54
  • @theonlygusti You could also try [threading.Condition.wait](https://docs.python.org/3/library/threading.html?highlight=wait#threading.Condition.wait) with a timeout. – Gribouillis Jan 01 '17 at 10:06
  • @hiroprotagonist I misread that comment too, but I think it was to the OP. A question was posed about whether there should be something inside the loop, then didn't want to use this solution. I'm confused about what's happening here, I don't get what the accepted answer addresses that this does not. Edit: I guess it's more explicit in that it includes code. – roganjosh Jan 01 '17 at 10:27
  • @roganjosh maybe if you read my comments you would; I need something that basically waits until a certain time. If the computer sleeps, then `time.sleep` doesn't accomplish this. – theonlygusti Jan 01 '17 at 10:30
  • @Lupe you are like a little child. "My solution works, agree with me so I feel justified." I never said that, you little baby. I am asking here for a better solution than the one I currently have, the reason I can't use this answer is because `time.sleep` isn't reliable if the computer sleeps or the thread is suspended. – theonlygusti Jan 01 '17 at 10:32
  • @theonlygusti ok, we have our wires crossed. Since your question was whether something needed to be within the `while` loop, I always read this answer as implying that you put a brief `sleep` inside the loop. – roganjosh Jan 01 '17 at 10:33
  • @hiroprotagonist I apologize everyone, the way the question was being asked irritated me and I was less kind than I should have been. But hiro it was to the op, not you. I agree entirely with your solution. – Lupe Jan 01 '17 at 11:40
2

maybe putting time.sleep(1) in the while loop will require less cycles? Or

def block_for(seconds):
    """Wait at least seconds, this function should not be affected by the computer sleeping."""
    end_time = datetime.datetime.now() + datetime.timedelta(seconds=seconds)

    while datetime.datetime.now() < end_time - datetime.timedelta(seconds=1):
        time.sleep(1)

    while datetime.datetime.now() < end_time:
        pass
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
Adrijaned
  • 430
  • 6
  • 13
  • For me, `datetime.timedelta(1)` seems to return a delay of a day. – theonlygusti Jan 01 '17 at 09:48
  • 1
    `datetime.timedelta(seconds=1)` is what you mean (right?). – hiro protagonist Jan 01 '17 at 09:51
  • @theonlygusti You may want to use a smaller delay, eg `time.sleep(0.2)`. And it would be more efficient to compute `end_time - datetime.timedelta(seconds=1)` outside the `while` loop, but I guess that's not a big deal. – PM 2Ring Jan 01 '17 at 10:18
  • 1
    @PM2Ring I have already done that, my solution looks like `end_time = datetime.datetime.now() + datetime.timedelta(seconds=seconds) while datetime.datetime.now() < end_time: time.sleep(1)` – theonlygusti Jan 01 '17 at 10:20
  • What is the point of the two `while` loops in this answer? The second one exits almost immediately after the first one exits. The second one seems completely redundant aside from _maybe_ using a few _more_ cycles? – Chris Larson Jan 01 '17 at 12:13
  • @ChrisLarson I haven't used it in my project, but it is obviously to improve resolution – theonlygusti Jan 01 '17 at 12:26
  • Does your project need resolution below 1 second? If that's the case, there may be a better approach overall in some of the higher precision modules. Bearing in mind that any use case that involves the MacBook going to sleep is going to throw any resolution completely out the window. – Chris Larson Jan 01 '17 at 12:33