1

My Code

from twisted.internet import task, reactor

def stuff():
    print('Hello, world!')

scheduler = task.LoopingCall(stuff())
scheduler.start(10)
reactor.run()

This is the Error I am getting

Hello, world! Unhandled error in Deferred:

Traceback (most recent call last): File "C:\Users\Usama fiaz\AppData\Local\Programs\Python\Python39\lib\site-packages\twisted\internet\base.py", line 1315, in run self.mainLoop() File "C:\Users\Usama fiaz\AppData\Local\Programs\Python\Python39\lib\site-packages\twisted\internet\base.py", line 1325, in mainLoop reactorBaseSelf.runUntilCurrent() File "C:\Users\Usama fiaz\AppData\Local\Programs\Python\Python39\lib\site-packages\twisted\internet\base.py", line 991, in runUntilCurrent call.func(*call.args, **call.kw) File "C:\Users\Usama fiaz\AppData\Local\Programs\Python\Python39\lib\site-packages\twisted\internet\task.py", line 251, in call d = maybeDeferred(self.f, *self.a, **self.kw) --- --- File "C:\Users\Usama fiaz\AppData\Local\Programs\Python\Python39\lib\site-packages\twisted\internet\defer.py", line 190, in maybeDeferred result = f(*args, **kwargs) builtins.TypeError: 'NoneType' object is not callable

Usama Fayyaz
  • 41
  • 2
  • 7

2 Answers2

1

Per the API documentation, LoopingCall.__init__ accepts a callable parameter f as its first argument.

In your example:

from twisted.internet import task, reactor

def stuff():
    print('Hello, world!')

scheduler = task.LoopingCall(stuff())
scheduler.start(10)
reactor.run()

the value being passed for f is the result of evaluating stuff() - in other words, it is the return value of the stuff function. stuff implicitly returns None so your LoopingCall construction is equivalent to:

scheduler = task.LoopingCall(stuff())

Then, when you start the loop with LoopingCall.start you don't attach any error handlers. When LoopingCall tries to call None an exception is raised. Since there are no error handlers attached, the exception is reported as an "Unhandled error in Deferred" and logged for you.

If you want the LoopingCall to call stuff at the defined interval, pass stuff to it (instead of None). If you want to deal with errors in your loop, attach an error handler to the Deferred returned by LoopingCall.start.

Jean-Paul Calderone
  • 47,755
  • 6
  • 94
  • 122
0

Remove parentheses () to pass a function as a callback

def stuff():
    print('Hello, world!')

scheduler = task.LoopingCall(stuff)  # this is a callback

In this way, you just call the function and pass the None return value

scheduler = task.LoopingCall(stuff())  # this is a function call
Dorin
  • 1,016
  • 1
  • 11
  • 15