I am trying to threading to call a function with args, but the Syntax I use says I am using to many args... but 2 are needed to are given... so why?
import threading
import time
class Baab():
def finc(phrase):
time.sleep(3)
print(phrase)
def fenc():
time.sleep("last")
def fanc(ophrase):
print(ophrase)
def func(phrase, ophrase):
b = Baab()
b.fanc(ophrase)
b.finc(phrase)
b.fenc()
th = threading.Thread(target=func, args=("baba", "lol"))
th.start()
time.sleep(1)
print("second")
The class methods expect a self attribute explicitly.
Try changing your class method as below:
class Baab():
def finc(self, phrase):
time.sleep(3)
print(phrase)
def fenc(self):
time.sleep("last")
def fanc(self, ophrase):
print(ophrase)
Related
I defined a class with two methods: StartRecording and StopRecording. The former implements a while loop for data recording in real-time, the latter breaks the recording.
The while loop works until the elapsed time exceed a constant value. Let's say 3000ms.
Here is the Python code.
class MyClass():
def StartRecording(self):
...
while elapsedTime < 3000:
#do something
def StopRecording(self):
...
#do something
I would like to transform the break condition of the while loop. So I decided to use a boolean variable declared in the init and to modify its value in the StopRecording function.
class MyClass():
def __init__(self):
self.m_lock = Lock()
self.isRecording = None
def StartRecording(self):
...
self.isRecording = True
while self.isRecording:
#do something
def StopRecording(self):
...
self.isRecording = False
#do something
The class is defined in a module which is called from another script
import MyClassFile as mcf
import time
device = mcf.MyClass()
device.StartRecording()
time.sleep(3)
device.StopRecording()
Unfortunately, the recording doesn't stop! How can I modify it properly?
Following your example:
import MyClass as mc
import time
mc.StartRecording()
time.sleep(3)
mc.StopRecording()
You should create an instance of the class and then use that to start and stop the recording:
import MyClass as mc
import time
recorder_instance = mc()
recorder_instance.StartRecording()
time.sleep(3)
recorder_instance.StopRecording()
I am trying to figure out how to pass a string as an argument in Python threading.Thread. This problem has been encountered before: Python Threading String Arguments
Is there a better way to pass in a string? There has to be a more obvious way, and I am just too new to coding to figure it out.
Code Block A
import threading
def start_my_thread():
my_thread = threading.Thread(target=my_func, args="string")
my_thread.start()
def my_func(input):
print(input)
Result:
TypeError: my_func() takes 1 positional argument but 6 were given
Code Block B
import threading
def start_my_thread():
my_thread = threading.Thread(target=my_func, args=("string",))
my_thread.start()
def my_func(input):
print(input)
Result: string
you can inherit Thread,and define my_func as run method.and create a new instance.
import threading
class MyThread(threading.Thread):
def __init__(self,string):
super().__init__()
self.string = string
def run(self):
print(self.string)
# def start_my_thread():
# my_thread = threading.Thread(target=my_func, args=("string",))
# my_thread.start()
# def my_func(input):
# print(input)
if __name__ == "__main__":
MyThread("hello").start()
I am trying to create a simple callback that can be registered to an object from another thread. The initial object that calls the callback is running on its own thread in this case.
This is best illustrated through the following example:
from pprint import pprint
import sys
import weakref
import threading
import time
class DummyController(object):
def __init__(self):
self.name = "fortytwo"
def callback(self):
print("I am number : " + self.name)
class SomeThread(threading.Thread):
def __init__(self, listener):
threading.Thread.__init__(self)
self.listener = listener
def run(self):
time.sleep(1)
dummy = DummyController()
self.listener.register_callback(dummy.callback)
time.sleep(5)
del dummy
class Listener(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.runner = weakref.WeakMethod(self.default_callback)
self.counter = 20
def default_callback(self):
print("Not implemented")
def register_callback(self, function):
self.runner = weakref.WeakMethod(function)
def run(self):
while self.counter:
try:
self.runner()()
except Exception as e:
pprint(e)
self.counter -= 1
time.sleep(1)
listen = Listener()
some = SomeThread(listen)
listen.start()
some.start()
Now the above code works just fine. But I am concerned about thread-safety here. Reading through weakref docs, it isn't very clear if weakref is really thread safe or not, except for the line:
Changed in version 3.2: Added support for thread.lock, threading.Lock, and code objects.
I might be simply not reading that right. Do I need to add locking, or is everything actually fine and pretty thread safe?
Many thanks
OK, I understand. This is not a problem about thread safe, but just a problem about weak reference.
There is an executable example:
from pprint import pprint
import sys
import weakref
import threading
import time
import gc
class SomeThread(threading.Thread):
def __init__(self, listener):
threading.Thread.__init__(self)
self.listener = listener
def run(self):
class test: # simplify this example.
def callback(self, count):
print(count)
time.sleep(1)
dummy = test()
self.listener.register_callback(dummy.callback)
time.sleep(5)
del dummy
gc.collect() # add this line to do garbage collecting.
class Listener(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.runner = weakref.WeakMethod(self.default_callback)
self.counter = 20
def default_callback(self):
print("Not implemented")
def register_callback(self, function):
self.runner = weakref.WeakMethod(function)
def run(self):
while self.counter:
try:
self.runner()(self.counter)
except Exception as e:
pprint(e)
self.counter -= 1
time.sleep(1)
listen = Listener()
some = SomeThread(listen)
listen.start()
some.start()
output:
TypeError('default_callback() takes 1 positional argument but 2 were given',)
TypeError('default_callback() takes 1 positional argument but 2 were given',)
18
17
16
15
TypeError("'NoneType' object is not callable",)
TypeError("'NoneType' object is not callable",)
TypeError("'NoneType' object is not callable",)
If you explicitly call gc.collect(), callback loses its last strong reference and then it becomes None. As you will never know when will gc collect garbage, there is a potential issue.
It is no matter you use thread or not, just a normal behave of weak reference.
BTW, be careful that exiting SomeThread.run will also implicitly del dummy, you can test it by removing del dummy and moving gc.collect() into try block.
Trying to call two methods say_hello and say_world by getattr() in multiprocessing.Process, but method say_world hasn't been executed. How can I make it possible? Thanks.
# -*- coding: utf-8 -*-
from multiprocessing import Process
import time
class Hello:
def say_hello(self):
print('Hello')
def say_world(self):
print('World')
class MultiprocessingTest:
def say_process(self, say_type):
h = Hello()
while True:
if hasattr(h, say_type):
result = getattr(h, say_type)()
print(result)
time.sleep(1)
def report(self):
Process(target=self.say_process('say_hello')).start()
Process(target=self.say_process('say_world')).start() # This line hasn't been executed.
if __name__ == '__main__':
t = MultiprocessingTest()
t.report()
The parameter target expects a reference to a function as value but your code passes None to it. These are the necessary parts to change:
class Hello:
def say_hello(self):
while True:
print('Hello')
time.sleep(1)
def say_world(self):
while True:
print('World')
time.sleep(1)
class MultiprocessingTest:
def say_process(self, say_type):
h = Hello()
if hasattr(h, say_type):
return getattr(h, say_type) # Return function reference instead of execute function
else:
return None
I'm trying to implement threading(with using decorators) to my application, but can't understand some things about locks and managing threads.
import threading
def run_in_thread(fn):
def run(*k, **kw):
t = threading.Thread(target=fn, args=k, kwargs=kw)
t.start()
return run
class A:
#run_in_thread
def method1(self):
for x in range(10000):
print x
#run_in_thread
def method2(self):
for y in list('wlkefjwfejwiefwhfwfkjshkjadgfjhkewgfjwjefjwe'):
print y
def stop_thread(self):
pass
c = A()
c.method1()
c.method2()
As I understand, method1 and method2 are not synchronized, but synchronizing of that stuff implementing with help of locks. How I can add locks to my decorator-function?
How can I realize method for stopping long threads using decorators?
If you extend the function to
def run_in_thread(fn):
def run(*k, **kw):
t = threading.Thread(target=fn, args=k, kwargs=kw)
t.start()
return t # <-- this is new!
return run
i. e., let the wrapper function return the created thread, you can do
c = A()
t1 = c.method1()
t1.join() # wait for it to finish
t2 = c.method2()
# ...
i. e, get the thread where the original method runs in, do whatever you want with it (e. g. join it) and only then call the next method.
If you don't need it in a given case, you are free to omit it.
If you want to synchronize the two threads you simply need to add locks inside the decorated functions, not the decorators themselves.
There is not a simple way to directly stop a Thread, only way is to use an Event to signal the thread it must exit.
For threading decorators you can take a look at pebble.
Maybe Semaphores could help in decorators, something like this - calculating factorial numbers from 1 to 1000:
import threading
from functools import wraps
from math import factorial
DIC = {}
def limit(number):
''' This decorator limits the number of simultaneous Threads
'''
sem = threading.Semaphore(number)
def wrapper(func):
#wraps(func)
def wrapped(*args):
with sem:
return func(*args)
return wrapped
return wrapper
def async(f):
''' This decorator executes a function in a Thread'''
#wraps(f)
def wrapper(*args, **kwargs):
thr = threading.Thread(target=f, args=args, kwargs=kwargs)
thr.start()
return wrapper
#limit(10) # Always use #limit as the outter decorator
#async
def calcula_fatorial(number):
DIC.update({number: factorial(number)})
#limit(10)
def main(lista):
for elem in lista:
calcula_fatorial(elem)
if __name__ == '__main__':
from pprint import pprint
main(range(1000))
pprint(DIC)