2

I am just trying to understand that if when I call time.sleep(x), the current thread that is running the code gets delayed by x seconds. But does that free up the processor for those x seconds or does the thread keep the resources to itself and after x seconds it just starts executing the next lines of code.

Editing with the exact scenario I am facing:

Here's the case with me:

class SomeHandler(tornado.websocket.WebSocketHandler)
  @tornado.gen.coroutine
  def something_async():
    time.sleep(5)
    return result

  def on_message(message):
    future = yield something_async(message)

if __name__ == '__main__':
  application = tornado.web.Application([
    (r'/', SomeHandler),
  ])

  http_server = tornado.httpserver.HTTPServer(application)
  http_server.listen(8888)
  tornado.ioloop.IOLoop.instance().start()

Now since this Tornado will be a single threaded server, What exactly does time.sleep(5) do in this case (will it just block the thread for 5 seconds making the whole process synchronous) or the coroutine spawns a new thread?

Ishan Sharma
  • 115
  • 2
  • 9
  • 2
    Would it make sense to hog the CPU and prevent any other thread from executing? Is there perhaps a way you could find out? – Ulrich Eckhardt Mar 28 '16 at 10:13
  • 3
    Maybe this can help you: http://stackoverflow.com/questions/92928/time-sleep-sleeps-thread-or-process – Querenker Mar 28 '16 at 10:15
  • The simple answer is that it will free the processor, but the implementation might vary. There is a feature known as a *spin lock* whereby a thread retains the CPU if the wait is for a short time. It is conceivable that an implementation could use a spin lock for short sleep times, particularly on Windows where there is an API specifically for that. See also http://stackoverflow.com/questions/7273474/behavior-of-pythons-time-sleep0-under-linux-does-it-cause-a-context-switch and http://stackoverflow.com/questions/22115831/how-to-resolve-spinlock-issues-with-multithreaded-python – cdarke Mar 28 '16 at 10:33

3 Answers3

3

An example is always best:

#!/usr/bin/env python
# -*- coding: utf-8; py-indent-offset:4 -*-
###############################################################################
from __future__ import (absolute_import, division, print_function)
#                        unicode_literals)

import threading
import time


def func1():
    time.sleep(10)
    print('Func1: Out of sleep and returning')


def func2(flag):
    while not flag:
        time.sleep(1)
        print('Func2: looping')

    print('Func2: Flag set, leaving')


t1 = threading.Thread(target=func1)
f = list()

t2 = threading.Thread(target=func2, kwargs=dict(flag=f))

t1.start()
t2.start()

t1.join()
f.append(None)

With output:

Func2: looping
Func2: looping
Func2: looping
Func2: looping
Func2: looping
Func2: looping
Func2: looping
Func2: looping
Func2: looping
Func1: Out of sleep and returning
Func2: looping
Func2: Flag set, leaving

It should be obvious from the output that even if t1 (the 1st thread) is blocked in a long time.sleep of 10 seconds, the 2nd thread t2 is running.

And even when t1 is done we see that the main thread is able to append to the list which is being used as a flag to let t2 understand it has to return and therefore end.

So: time.sleep only blocks the thread in which is being executed.

mementum
  • 3,153
  • 13
  • 20
  • Thanks mementum for the detailed example. I've just added the whole scenario I am in, can you please comment on that? – Ishan Sharma Mar 28 '16 at 12:20
  • As commented by others and seeing your full code now, the problem is you are blocking the main thread. Use the hint suggested by A. Jesse Jiryu Davis – mementum Mar 28 '16 at 16:00
2

Tornado never spawns a thread for you.* If you call time.sleep, it blocks the entire process for the duration of the sleep; no other processing proceeds. This is why the docs say "time.sleep should not be used in coroutines because it is blocking". To explicitly pause a coroutine and return control to the IOLoop so other processing can proceed:

yield gen.sleep(0.5)

* Tornado can spawn threads for DNS resolution or when you explicitly use a ThreadPoolExecutor to make a task asynchronous. But you can ignore these cases for this discussion.

A. Jesse Jiryu Davis
  • 23,641
  • 4
  • 57
  • 70
  • One another little problem, what if I want to use yield gen.sleep(0.5) in some function that is already returning a value? Python < 3.3 doesn't support that. What else can be done in that case? – Ishan Sharma Mar 28 '16 at 13:15
  • To return a value from a coroutine in Python 2, "raise gen.Return(value)": http://www.tornadoweb.org/en/stable/gen.html#tornado.gen.Return – A. Jesse Jiryu Davis Mar 28 '16 at 14:49
  • I still don't understand. Can you write a brief example to explain? ' def add(x,y): yield gen.sleep(countdown); a = x+y; raise gen.Return(a); How to get the value a by calling this function? – Ishan Sharma Mar 29 '16 at 10:18
  • Sure! Everything you need to know is written here: https://emptysqua.re/blog/refactoring-tornado-coroutines/ – A. Jesse Jiryu Davis Mar 29 '16 at 13:38
0

you can use the code inside function:

import time
time.sleep(2) # put value here as seconds, 2 is 2 seconds

OR

from time import sleep
sleep(60) # put value here as seconds, 60 is 60 seconds = 1 minute

Example code:

import time
def function1():
    print('function1 is sleeping for 2 seconds...')
    time.sleep(2)

count = 0
while True:
    if count >= 10:
        break
    function1()
    count=count+1

For further details please visit : https://docs.python.org/3/library/time.html#time.sleep

MD. SHIFULLAH
  • 913
  • 10
  • 16