Timer object returning argument Nº error - python

Was working on a simple timer function, but hit a wall. Code in question is:
#!/usr/bin/python3
import threading
Timer = threading.Timer()
def hello():
print "hello, world"
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
Code is a direct copy of the one in https://docs.python.org/2/library/threading.html#timer-objects
Since the function hello takes no args I don't understand the error output of:
File "timer_test.py", line 3, in <module>
Timer = threading.Timer()
File "C:\Python27\lib\threading.py", line 1047, in Timer
return _Timer(*args, **kwargs)
TypeError: __init__() takes at least 3 arguments (1 given)
Does the Timer require another argument other then the time itself and the function to be executed? Shouldn't the args/kwargs not need to be passed since the function hello takes none? I tried passing arbitrary arguments such as None or [] but it changed nothing.
I know it's probably a stupid problem, but since the documentation doesn't answer me, and I couldn't find an answer already on here I decided to post this.
Thank you for your time/help

It is not a direct copy. It has an extra line:
Timer = threading.Timer()
In this line, you try to create a time, but do not pass the delay and function arguments.
More on that, if that would work, you override the class name Timer with an object of the timer, and try to create another timer, but from an instance, not from the class. That will never work.
Remove that line, and make it exactly as in the docs.

Related

Unable to schedule anything in asyncio. (Python 3.7.x)

I am currently working on asyncio with python 3.7.x not sure about the exact version, right now I am trying to schedule a task. And I am unable to get an output, even when running the thing forever. Here is the code I currently have
import asyncio
async def print_now():
print("Hi there")
loop = asyncio.get_event_loop()
loop.call_later(print_now())
loop.run_until_complete(asyncio.sleep(1))
This gives the following error:
Traceback (most recent call last):
File "D:\Coding\python\async\main.py", line 7, in <module>
loop.call_later(print_now())
TypeError: call_later() missing 1 required positional argument: 'callback'
The call back in call_later() is print_now I've tried just print_now and print_now()
I have also tried using loop.run_forever() instead of loop.run_until_complete() and so far I didn't get anything
Sometimes I get either no output or a different error.
First, yes, you're missing a delay argument . First one is supposed to be the delay while the second one is a callback (docs).
loop.call_later(delay, callback, *args, context=None)
Second, the callback is supposed to be a function. What you're passing is print_now() which is gonna evaluate to None. You might find out that
'NoneType' object is not callable
So you're gonna need to pass print_now — without parentheses — as a callback. This way you're passing a function instead of the result of its application.
Third, async functions are supposed to be awaited on. Your scenario doesn't seem to need that, so just drop the async keyword.
When you call an awaitable function, you create a new coroutine object. The code inside the function won't run until you then await on the function or run it as a task
From this post. You might want to check out

tkinters mainloop has trapped my foo

I've seen numerous question on this site, where people ask how user-written code, say a function foo, can be executed in tkinter's mainloop, e.g. this or this. Two alternatives exist: Use the after method, or use threading. I'd like to know more about how the after method actually works.
More precisely, inspired by this excellent article, where a very high-level description of how the GIL in Python works is given, I'd like to know more how the after method works in terms of the Python interpreter processing foo inside tkinter's mainloop.
I'm particularly confused how the CPython interpreter steps through the code, when I insert code using after. How is foo ending up being executed by tkinter's mainloop?
What I found so far:
Bryan Oakley, quoted from the first link, says: "after does not create another thread of execution. Tkinter is single-threaded. after merely adds a function to a queue."
But inspecting the source code
def after(self, ms, func=None, *args):
"""Call function once after given time.
MS specifies the time in milliseconds. FUNC gives the
function which shall be called. Additional parameters
are given as parameters to the function call. Return
identifier to cancel scheduling with after_cancel."""
if not func:
# I'd rather use time.sleep(ms*0.001)
self.tk.call('after', ms)
else:
def callit():
try:
func(*args)
finally:
try:
self.deletecommand(name)
except TclError:
pass
callit.__name__ = func.__name__
name = self._register(callit)
return self.tk.call('after', ms, name)
doesn't really help me, as it doesn't reveal the answers to these questions, and I'm a novice programmer, so I don't really understand how to trace this further.
I'd like to know more about how the after method actually works.
mainloop is just an endless loop which scans some internal queues to see if there are any events to process. Think of it as if it was implemented something like this:
def mainloop():
while the_window_exists():
if len(after_queue) > 0:
event = after_queue.pop()
if event.time_to_execute >= time.time():
event.command(**event.args)
if len(event_queue) > 0:
...
It's not literally implemented that way -- it's a bit more efficient and there's a little more going on, but logically it's nearly identical.
When you call after, it simply puts something on the "after" queue. Nothing more, nothing less.
Using the same analogy, after might be implemented something like this:
def after(delay, code_to_run, *args):
event = Event()
event.code_to_run = code_to_run
event.args = args
event.time_to_execute = time.time() + delay
event_queue.append(event)
That's all there is to it. You're putting something on a queue when you call after, and mainloop pulls things off of that queue. It all happens in the same thread.
To mainloop, the function you added with after is no different than a function that gets added when you move the mouse or press a button -- it's just an event object on a queue.

Thread seems to be blocking the process

class MyClass():
def __init__(self):
...
def start(self):
colorThread = threading.Thread(target = self.colorIndicator())
colorThread.start()
while True:
print ('something')
...
...
I also have a print statement inside the colorIndicator(). That statement is getting printed. But the print statement inside the while loop of start() method isn't displayed on screen.
The colorIndicator() also has an infinite loop. It gets some data from the internet and updates a counter. This counter is initialized inside __init__ as self variable and I'm using that variable inside other methods.
I do not understand why print inside while is not being executed.
colorIndicator function:
def colorIndicator(self):
print ('something else')
...
while (True):
...
print ('here')
time.sleep(25)
The output I get is the following:
something else
here
here
I stopped it after that. So, the colorIndicator is clearly running completely.
I'm calling the script with import in a python interpreter (in a terminal). Then I instantiate MyClass and call the start function.
You're not actually running colorIndicator in a thread, because you called it in the main thread, rather than passing the method itself (uncalled) as the thread target. Change:
colorThread = threading.Thread(target=self.colorIndicator())
# ^^ Agh! Call parens!
to:
# Remove parens so you pass the method, without calling it
colorThread = threading.Thread(target=self.colorIndicator)
# ^ Note: No call parens
Basically, your problem is that before you ever construct the Thread, it's trying to run colorIndicator to completion so it can use its return value as the target, which is wrong in multiple ways (the method never returns, and even if it did, it wouldn't return a callable suitable for use as a target).

Quitting a Python program

I am trying to quit a python program by calling sys.exit() but it does not seem to be working.
The program structure is something like:
def func2():
*does some scraping operations using scrapy*
def func1():
Request(urls, callbakc=func2)
So, here, func1 is requesting a list of URLs and the callback method, func2 is being called. I want to quit the execution of the program if something goes wrong in func2
On checking the type of the object in func1 I found its and http.Request object.
Also, since I am using scrapy, whenever I call sys.exit() in func2, the next url in the list is called and the program execution continues.
I have also tried to use a global variable to stop the execution but to no avail.
Where am I going wrong?
According to the How can I instruct a spider to stop itself?, you need to raise CloseSpider exception:
raise CloseSpider('Done web-scraping for now')
Also see:
Running Scrapy tasks in Python
sys.exit() would not work here since Scrapy is based on twisted.
Even if we don't know how to completely stop, Python's mutable-object default binding "gotcha" can help us skip all callbacks from a certain point on.
Here is what you can do:
First, create a function generating wrapping other callback functions with condition. It's second argument cont is going to be bound to a mutable object (list) so we can affect all callbacks after creating them.
def callback_gen(f, cont=[True]):
def c(response):
if cont[0]:
f(response, cont=cont)
else:
print "skipping" # possibly replace with pass
return c
Now make some testing functions:
def func2(response, cont=None):
print response
print cont
# this should prevent any following callback from running
cont[0]=False
def func3(response, cont=None):
print response
print cont
And now create two callbacks the first one is func2 which prevents the following ones from running.
f2 = callback_gen(func2)
f3 = callback_gen(func3)
f2("func2")
f3("func3")
I like it :)

python threading.Timer start immediately not at specified time

i want to execute a function in every 3 second
the code works if i call a function without arguments like below:
def mytempfunc():
print "this is timer!"
threading.Timer(5, mytempfunc).start()
but if i call a function with argument like this:
def myotherfunc(a,b,c,d):
print "this is timer!"
threading.Timer(5, myotherfunc(a,b,c,d)).start()
the new thread will be created and started immediately without waiting for 5 seconds.
is there anything that i missed?
Try this:
threading.Timer(5, myotherfunc, [a,b,c,d]).start()
In your code, you actually call myotherfunc(a,b,c,d), rather than passing your function and arguments to the Timer class.

Categories

Resources