Consider the following code:
from threading import Thread
def main():
number = 5
class my_thread(Thread):
def __init__(self, range):
Thread.__init__(self)
self.range = range
def run(self):
global number
for i in self.range:
number += 1
t1 = my_thread(range(4))
t1.start()
t1.join()
print number
main()
The output from this program is
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Tools\Python27\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Dev\Workspace\Hello World\Hello.py", line 14, in run
number += 1
NameError: global name 'number' is not defined
5
Evidently, my_thread does not have access to number. Why is this, and how can I access it correctly?
You need to make number a global at its first definition, like this:
def main():
global number
number = 5
...etc...
Related
I am trying to call different functions based on the value for rb_selection, calling func1 if rb_selection value is 0 and calling func2 if rb_selection value is 1. Both functions take a different set of arguments.
I do not need folder argument(func2 values) when I call func1 and similarly I do not need batch, term arguments(func1 values) when I call func2
It throws me the below error when I try to call the second function, as the values for batch, term are not passed.
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Himajak\Anaconda3\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "<ipython-input-13-02b5f954b815>", line 122, in tb_click
ThreadedTask(self.queue,self.batch_name,self.term_name,self.course,self.rb_selection,self.folder).start()
AttributeError: 'GUI' object has no attribute 'batch_name'
Code looks similar to this:
class class1():
def def1(self):
self.queue = queue.Queue()
ThreadedTask(self.queue,self.rb_selection,self.batch_name,self.folder).start()
#self.master.after(10, self.process_queue)
class class2():
def __init__(self, queue,rb_selection, batch_name ,term_name, folder):
threading.Thread.__init__(self)
self.queue = queue
self.rb_selection = rb_selection
self.batch = batch_name
self.term = term_name
self.folder = folder
def func1(self,batch,term):
time.sleep(5)
print("Fucntion 1 reached")
print(self.batch,self.term)
def func2(self,folder):
time.sleep(5)
print("Function 2 reached")
print(self.folder)
def run(self):
time.sleep(0) # Simulate long running process
if self.rb_selection == '0':
self.func1(self.batch,self.term)
elif self.rb_selection == '1':
self.func2(self.folder)
self.queue.put("Task finished")
Please suggest on how to resolve this issue, thanks in advance!
There is no concept of optional arguments, you can give default value when creating the function like
def __init__(self, queue,rb_selection ,term_name, folder, batch_name="default batch name"):
So that you need not pass batch_name while creating the Instance.
I am trying to run a simple threading function within my simple class.
I am trying to call the Thread function within a method of a class. This Thread function within this method points to another method within the class. The way I tested it out is through the python terminal. Here is my class in increment_thread.py:
from threading import Thread
import time
class Increment:
def __init__(self):
self.count = 0
def add_one(self):
while True:
self.count = self.count + 1
time.sleep(5)
def start(self):
background_thread = Thread(target=add_one)
background_thread.start()
print("Started counting up")
return
def get_count(self):
return print(self.count)
In order to test this, I run python in my terminal, which prompt the python terminal.
Then, I run the following lines:
from increment_thread import Increment
inc = Increment()
inc.get_count() # Yields 0
inc.start()
I expect the thread to start and indicate "Started counting up", but instead I get the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "~/python-sandbox/increment_thread.py", line 14, in start
background_thread = Thread(target=add_one)
NameError: name 'add_one' is not defined
Is what I am trying to do possible?
In the Thread constructor should it not be target=self.add_one rather than target=add_one
To pass parameters:
from threading import Thread
import time
class Increment:
count = None
def __init__(self):
self.count = 0
def add_one(self, start_at=0):
self.count = start_at
while True:
self.count = self.count + 1
time.sleep(5)
def start_inc(self, start_at=count):
# Pass args parameter as a tuple
background_thread = Thread(target=self.add_one, args=(start_at,))
background_thread.start()
print("Started counting up")
return
def get_count(self):
return print(self.count)
if __name__ == "__main__":
inc = Increment()
inc.get_count() # Yields 0
inc.start_inc(start_at=5)
while True:
inc.get_count()
time.sleep(2)
Just like class fields, class methods need to be referred to using self.method syntax. So
def start(self):
background_thread = Thread(target=self.add_one)
background_thread.start()
print("Started counting up")
return
When i run the code below, i got an exception
# System
import time
import logging
import sys
import os
import threading
# cv2 and helper:
import cv2
class inic_thread(threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Starting " + self.name
if self.counter == 1: capture_continuos()
elif self.counter == 2: face_search()
def capture_continuos():
#os.system('python capture_continuos.py')
while(1):
print 'a'
def face_search():
# atributes
pool = []
path_pool = './pool/'
while(1):
pool_get = os.listdir(path_pool)
if len(pool_get) > 0:
#print(str(len(pool_get))+' images in the pool')
for image in pool_get:
print(image)
os.system('python face_search.py -i '+str(image))
else:
print('Empty Pool')
try:
capture_continuos = inic_thread(1, "capture_continuos_1", 1)
face_search_2 = inic_thread(2, "face_search_2", 2)
capture_continuos.start()
face_search_2.start()
except:
print("Error: unable to start thread")
But it don't make sense to me, because one of the threads run normal, (face_search) but the other one give this exception.
Starting capture_continuos_1
Exception in thread capture_continuos_1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "main.py", line 44, in run
if self.counter == 1: capture_continuos()
TypeError: 'inic_thread' object is not callable
What i'm doing wrong?
I run in a Raspberry Pi 3 model B with Ubuntu MATE 14.04; Python 2.7.12
At the bottom of your script you redefine variable capture_continuos assigning thread object to it.
Also as was mentioned to terminate thread it's better to call os._exit() instead of sys.exit().
I am trying to call method within a class; that call is the last line below, self.z()
class Wait:
def __init__(self,a):
self.a = a
def countdown(self,a):
for remaining in range(self.a, 0, -1):
sys.stdout.write("\r")
sys.stdout.write("{:2d} seconds remaining.".format(remaining))
sys.stdout.flush()
time.sleep(1)
sys.stdout.write("\rWait Complete! \n")
def z(self):
self.countdown(100)
self.z()
However, I get this error:
Traceback (most recent call last):
File "./countdown.py", line 6, in <module>
class Wait:
File "./countdown.py", line 18, in Wait
self.z()
NameError: name 'self' is not defined
How can I call countdown from another method within this class ?
The problem is that self is not defined in the class body; self is a parameter of each of the methods, but you're not inside any method at that point. I think you might be trying to test this with a 100-second countdown, which means that you need that bottom code in your main program:
class Wait:
def __init__(self,a):
self.a = a
def countdown(self,a):
for remaining in range(self.a, 0, -1):
sys.stdout.write("\r")
sys.stdout.write("{0:2d} seconds remaining.".format(remaining))
sys.stdout.flush()
time.sleep(1)
sys.stdout.write("\rWait Complete! \n")
def z(self):
self.countdown(100)
ticker = Wait(10)
ticker.z()
Note that your code ignores the 100 value sent in from z, instead using the timer value set at creation. Also note that I've corrected your formatted output statement.
Can you take it from here?
I have pretty simple code of worker, might be doing some silly mistake.
class BingWorker(object):
def __init__(self):
self.gm_worker = gearman.GearmanWorker(['localhost:4730'])
completed_job_request = self.gm_worker.register_task('bingmedia', callBing)
def callBing(self, gearman_worker, gearman_job):
print "In worker ", gearman_job.data
return "Kools"
def run(self):
self.gm_worker.work()
if __name__ == '__main__':
BingWorker().run()
gives
Traceback (most recent call last):
File "worker.py", line 16, in <module>
BingWorker().run()
File "worker.py", line 6, in __init__
completed_job_request = self.gm_worker.register_task('bingmedia', callBing)
NameError: global name 'callBing' is not defined
any hints? example is very similar to python example at http://gearman.org/examples/reverse/. just put in class structure
Improved code:
class BingWorker(object):
def __init__(self):
self.gm_worker = gearman.GearmanWorker(['localhost:4730'])
def callBing(self, gearman_worker, gearman_job):
print "In worker ", gearman_job.data
return "Kools"
def run(self):
completed_job_request = self.gm_worker.register_task('bingmedia', self.callBing)
self.gm_worker.work()
if __name__ == '__main__':
BingWorker().run()
You need to change callBing to self.callBing and it might be better to move the registration to the first line of the run method rather than the __init__ method.
The fist is because callBing is a reference to a missing global while self.callBing is a reference to the classes method. The second is because potentially you could get a call to self.callBing before init has finished which would be bad news.