python threading.Timer start immediately not at specified time - python

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.

Related

How to terminate exec() function in python if it takes too long?

I am trying to make a function that takes in user's code and runs it:
code = input("Your code: ")
def execute(c):
exec(c)
execute(code)
However, if the user enters in an infinite loop, the function runs forever.
Is there a way to terminate the exec() function if the function takes too long? For example, if the code takes longer than 15 seconds to execute, the programme terminates.
Thanks in advance.
There are multiple solutions,
For example you could pass a global variable stop condition and raise exception from inside the exec once condition has met.
Other solution would be to run exec in a separate thread/process and sending some stop signal once desired.
You can use wrapt_timeout_decorator
from wrapt_timeout_decorator import *
#timeout(15)
def execute(c):
exec(c)
code = input("Your code: ")
execute(code)
This will throw an exception if the function takes more than 15 sec to finish - TimeoutError: Function execute timed out after 15.0 seconds

Timer object returning argument NÂș error

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.

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 :)

self.after doesn't wait when passing value

I'm making a gui in python wich uses the serial port for sending commands. In my old script, without a gui, i used time.sleep(x) between the write commands (it is necessary for to commands to succeed). Now when i use a gui envrimont, i can't use sleep so i use after.
It works well, but:
I'm using Tkinter for my gui. When i press the button start , OnButtonClickSTART starts the other function after x time. With self.after i wait x secondes between every process. It works, but when i give a value with the function, it doesn't wait the given time.
def OnButtonClickSTART(self):
print "START"
self.button1.configure(state='disabled')
self.after(1000, self.waitmore)
def waitmore(self):
value = 5
print value
self.after(10000,self.waitmuchmore(value))
def waitmuchmore(self,value):
print value
self.after(10000,self.OnButtonClickSTOP)
def OnButtonClickSTOP(self):
print "STOP"
self.button1.configure(state='normal')
And isn't here a better way to execute a series of command , with a certain time between them. Like sleep, but works with 1 function and doesn't disable the gui.
Thx
Using self.waitmuchmore(value) will immediately call the waitmuchmore method. You need to use either a lambda expression or functools.partial to return a new function that will call waitmuchmore with value, and pass that to self.after instead:
lambda: self.waitmuchmore(value)
or
import functools
functools.partial(self.waitmuchmore, value)

Categories

Resources