• Uncategorized

About python : Python-Pass-or-Sleep-for-long-running-processes

Question Detail

I am writing an queue processing application which uses threads for waiting on and responding to queue messages to be delivered to the app. For the main part of the application, it just needs to stay active. For a code example like:

while True:
  pass

or

while True:
  time.sleep(1)

Which one will have the least impact on a system? What is the preferred way to do nothing, but keep a python app running?

Question Answer

I would imagine time.sleep() will have less overhead on the system. Using pass will cause the loop to immediately re-evaluate and peg the CPU, whereas using time.sleep will allow the execution to be temporarily suspended.

EDIT: just to prove the point, if you launch the python interpreter and run this:

>>> while True:
...     pass
... 

You can watch Python start eating up 90-100% CPU instantly, versus:

>>> import time 
>>> while True:
...     time.sleep(1)
... 

Which barely even registers on the Activity Monitor (using OS X here but it should be the same for every platform).

Why sleep? You don’t want to sleep, you want to wait for the threads to finish.

So

# store the threads you start in a your_threads list, then
for a_thread in your_threads:
    a_thread.join()

See: thread.join

If you are looking for a short, zero-cpu way to loop forever until a KeyboardInterrupt, you can use:

from threading import Event

Event().wait()

Note: Due to a bug, this only works on Python 3.2+. In addition, it appears to not work on Windows. For this reason, while True: sleep(1) might be the better option.

For some background, Event objects are normally used for waiting for long running background tasks to complete:

def do_task():
    sleep(10)
    print('Task complete.')
    event.set()

event = Event()
Thread(do_task).start()
event.wait()

print('Continuing...')

Which prints:

Task complete.
Continuing...

signal.pause() is another solution, see https://docs.python.org/3/library/signal.html#signal.pause

Cause the process to sleep until a signal is received; the appropriate handler will then be called. Returns nothing. Not on Windows. (See the Unix man page signal(2).)

I’ve always seen/heard that using sleep is the better way to do it. Using sleep will keep your Python interpreter’s CPU usage from going wild.

You don’t give much context to what you are really doing, but maybe Queue could be used instead of an explicit busy-wait loop? If not, I would assume sleep would be preferable, as I believe it will consume less CPU (as others have already noted).

[Edited according to additional information in comment below.]

Maybe this is obvious, but anyway, what you could do in a case where you are reading information from blocking sockets is to have one thread read from the socket and post suitably formatted messages into a Queue, and then have the rest of your “worker” threads reading from that queue; the workers will then block on reading from the queue without the need for neither pass, nor sleep.

Running a method as a background thread with sleep in Python

    import threading
    import time


    class ThreadingExample(object):
        """ Threading example class
        The run() method will be started and it will run in the background
        until the application exits.
        """

        def __init__(self, interval=1):
            """ Constructor
            :type interval: int
            :param interval: Check interval, in seconds
            """
            self.interval = interval

            thread = threading.Thread(target=self.run, args=())
            thread.daemon = True                            # Daemonize thread
            thread.start()                                  # Start the execution

        def run(self):
            """ Method that runs forever """
            while True:
                # Do something
                print('Doing something imporant in the background')

                time.sleep(self.interval)

    example = ThreadingExample()
    time.sleep(3)
    print('Checkpoint')
    time.sleep(2)
    print('Bye')

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.