Python3.4 A quest about create mul-threads - multithreading

look at this code:
def w(i):
print("%s start" % i)
time.sleep(10)
print("end %s waiting" % i)
class ss(threading.Thread):
def __init__(self, i):
threading.Thread.__init__(self)
self.i = i
def run(self):
print("%s start" % self.i)
time.sleep(10)
print("end %s waiting" % self.i)
c=ss("c")
c.start()
d=ss("d")
d.start()
threading.Thread(w("a")).start()
threading.Thread(w("b")).start()
the result is this:
c start
a start
d start
end c waiting
end a waiting
end d waiting
b start
end b waiting
Maybe you have been know my puzzle.I create thread via "threading.Thread" function,it not run synchronously.Is it global function just only one thread run one time?I use python3.4

threading.Thread(w("a")).start()
means execute w("a") and pass result to a threading.Thread() constructor. Instead of passing a callable object you are calling it. You need to separate function and it's arguments:
threading.Thread(target = w, args = ["a"]).start()

Related

How to reliably trigger __del__ method of object?

I would like to reliably call the __del__ method of an object immediately when it gets deleted. I am aware that this has been asked for python 2, but the documentation of python 3 claims that the __del__ method is called when the reference count reaches 0. However, this does not seem to be the case with my program
import time
class MyClass:
object_list = []
def __init__(self):
MyClass.object_list.append(self)
print("object initialized")
def __del__(self):
print("executing cleanup steps")
MyClass.object_list.remove(self)
a = MyClass()
b = MyClass()
c = MyClass()
print(len(MyClass.object_list))
del b
time.sleep(1)
print("sleep finished")
print(len(MyClass.object_list))
Try it online
What I want to achieve is to remove b from the object_list immediately when it is destroyed and also make the variable b inaccessible. So simply calling b.__del__() is not enough, I would need to also render b inaccessible.
Note: running first b.__del__() and then del b will lead to complaints when exiting the python interpreter.
Interestingly enough, a very similar program seems to call b.__del__() immediately when del b is executed.
import time
class MyClass:
counter = 0
def __init__(self, value):
self.value = value
print("object initialized")
MyClass.counter+=1
def __del__(self):
print("executing cleanup steps")
MyClass.counter-=1
a = MyClass(5)
b = MyClass(6)
c = MyClass(7)
print(MyClass.counter)
del b
time.sleep(1)
print("sleep finished")
print(MyClass.counter)
Try it online
EDIT
#Pranav Hosangadi pointed out that there is still a reference to the object in the object_list. What a shameful oversight of mine. Now I came up with a workaround by calling first b.__del__() and then del b, but it is a two step process. I would like to have it in one step, if possible.
import time
class MyClass:
object_list = []
def __init__(self, value):
self.value = value
MyClass.object_list.append(self)
print("object initialized")
def __del__(self):
print("executing cleanup steps")
try:
MyClass.object_list.remove(self)
except:
pass
a = MyClass(1)
b = MyClass(2)
c = MyClass(3)
print(len(MyClass.object_list))
b.__del__()
del b
time.sleep(1)
print("sleep finished")
print(len(MyClass.object_list))

How to stop a cycling thread

I have a cycling threading method like this:
def make_periodic(self, method, period_sec, *args):
method(*args)
parameters = [method, period_sec] + list(args)
threading.Timer(period_sec, self.make_periodic, parameters).start()
What is the best way to stop the the cycling of a method of one type?
For example:
import threading
class TestThreading:
PERIOD = 5
def __init__(self):
self.number = 0
self.text = "t"
def method_1(self):
print self.number
self.number += 1
def method_2(self, text):
print self.text
self.text += text
def make_periodic(self, method, period_sec, *args):
method(*args)
parameters = [method, period_sec] + list(args)
threading.Timer(period_sec, self.make_periodic, parameters).start()
if __name__ == '__main__':
test = TestThreading()
test.make_periodic(test.method_1, TestThreading.PERIOD)
test.make_periodic(test.method_2, TestThreading.PERIOD, "t")
# stops the cycling of method_2, but the method_1 continues
test.stop_threading(test.method_2)
Try to keep a reference for each timer in a dictionary: my_dict["method_name"] = timer. In that case when you decide to stop the timer just call my_dict["method_name"].cancel().

threading.Timer join() quits immediately?

Since threading.Timer is a subclass of Thread, I would expect that the .join() in this script would cause the code to print "woof" once a second, continually:
import threading
def target_action(arg):
print arg
def start_timer_proc(interval, arg):
timer = threading.Timer(interval, target_action, [arg])
timer.start()
return timer
def main():
timer = start_timer_proc(1.0, "woof")
timer.join()
print("...exiting")
main()
Instead, it prints out "woof" once and then terminates (without any error message). What am I missing?
Here's what I really wanted (based loosely on https://stackoverflow.com/a/12435256/558639):
import threading
class IntervalTimer(threading.Thread):
def __init__(self, target_action, interval, args=[]):
threading.Thread.__init__(self)
self.event = threading.Event()
self.target_action = target_action
self.interval = interval
self.args = args
def start(self):
while not self.event.wait(self.interval):
self.target_action(*self.args)
def target_action(arg):
print arg
def start_timer_proc(interval, arg):
timer = IntervalTimer(target_action, interval, [arg])
timer.start()
return timer
def main():
timer = start_timer_proc(1.0, "woof")
print timer
timer.join()
print("...exiting")
main()
Note that I didn't need to change my target_action() or start_timer_proc() methods, except to instantiate an IntervalTimer rather than a Timer.

Timer runs only once in python

The following program print hello world only once instead it has to print the string for every 5 seconds.
from threading import Timer;
class TestTimer:
def __init__(self):
self.t1 = Timer(5.0, self.foo);
def startTimer(self):
self.t1.start();
def foo(self):
print("Hello, World!!!");
timer = TestTimer();
timer.startTimer();
(program - 1)
But the following program prints the string for every 5 seconds.
def foo():
print("World");
Timer(5.0, foo).start();
foo();
(program - 2)
Why (program - 1) not printing the string for every 5 seconds ?. And how to make the (program - 1) to print the string for every 5 seconds continuously.
(program - 2) prints a string every 5 seconds because it is calling itself recursively. As you can see, you call foo() function inside itself and this is the reason because it works.
If you want to print a string every 5 secs in (program - 1) using a class you could (but it's not really a good practice!):
from threading import Timer
class TestTimer:
def boo(self):
print("World")
Timer(1.0, self.boo).start()
timer = TestTimer()
timer.boo()
As has been pointed out, you're calling the foo() recursively:
def foo():
print("World");
Timer(5.0, foo).start(); # Calls foo() again after 5s and so on
foo();
In your question, you've created a wrapper around threading.Timer - I suggest you simply subclass it:
from threading import Timer
class TestTimer(Timer):
def __init__(self, i):
self.running = False
super(TestTimer, self).__init__(i, self.boo)
def boo(self):
print("Hello World")
def stop():
self.running = False
super(TestTimer, self).stop()
def start():
self.running = True
while self.running:
super(TestTimer, self).start()
t = TestTimer(5)
t.start()

Python 3 control multiprocessing

I am trying to write function using Python multiprocessing that i can control it and pass "command" to cleanly terminate the process.
I looked for few examples and tried it out ,but didn't seems to work fro me
So basically i need to to run separate process function code that doing some while loop action
and when needed stop it by passing somehow command and exit
Please advice
Thanks
example 1
from multiprocessing import Process, Queue
def start_process(queue):
while True:
try:
m = queue.get()
if m == 'exit':
print ('cleaning up worker...')
# add here your cleaning up code
break
else:
print (m)
except KeyboardInterrupt:
print ('ignore CTRL-C from worker')
if __name__ == '__main__':
queue = Queue()
process = Process(target=start_process, args=(queue,))
process.start()
queue.put(12)
try:
process.join()
except KeyboardInterrupt:
print ('wait for worker to cleanup...')
queue.put('exit')
process.join()
example 2
import multiprocessing
import time
class MyProcess(multiprocessing.Process):
def __init__(self, ):
multiprocessing.Process.__init__(self)
self.exit = multiprocessing.Event()
def run(self):
while not self.exit.is_set():
pass
print ("You exited!")
def shutdown(self):
print ("Shutdown initiated")
self.exit.set()
if __name__ == "__main__":
process = MyProcess()
process.start()
print ("Waiting for a while")
time.sleep(3)
process.shutdown()
time.sleep(3)
print ("Child process state: %d" % process.is_alive())
both examples works fine for me - perhaps you're misunderstanding how they should work?
in the first example, when the main thread runs, it starts the child and sends 12. then it waits to join the child. at that point everything is stalled because the child is waiting for 'exit'. but if you then hit ctrl-C the 'exit' is sent, the child exits, and the second join is successful:
> python3.3 example1.py
12
^Cignore CTRL-C from worker
wait for worker to cleanup...
cleaning up worker...
>
if you just want the parent to send 'exit' and then for everything to end, use:
def start_process(queue):
while True:
try:
m = queue.get()
if m == 'exit':
print ('cleaning up worker...')
# add here your cleaning up code
break
else:
print (m)
except KeyboardInterrupt:
print ('ignore CTRL-C from worker')
print('goodbye cruel world')
if __name__ == '__main__':
queue = Queue()
process = Process(target=start_process, args=(queue,))
process.start()
queue.put(12)
print ('sending exit')
queue.put('exit')
process.join()
which gives:
> python3.3 my-example.py
sending exit
12
cleaning up worker...
goodbye cruel world
>
your second example also works (with the indentation fixed):
> python3.3 example2.py
Waiting for a while
Shutdown initiated
You exited!
Child process state: 0
>
(just wait a little). not sure what else you could have expected here.

Resources