calling method within class in python - python

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?

Related

How to add optional arguments in a python class?

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.

How to run a threading function within a class?

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

How to access global variables from a thread in Python

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...

AssertionError: None is not callable

I'm in the process of learning how to program in twisted, and going through Dave Peticolas' tutorial (http://krondo.com/wp-content/uploads/2009/08/twisted-intro.html). I'm trying to solve the suggested exercise at the end of Part 3 - having multiple independent countdowns going on countdown.py. Here is my code, and the error I'm getting:
#!/usr/bin/python
class countdown(object):
def __init__(self):
self.timer = 0
def count(self, timer):
if self.timer == 0:
reactor.stop()
else:
print self.timer, '...'
self.timer -= 1
reactor.callLater(1, self.count)
from twisted.internet import reactor
obj = countdown()
obj.timer = 10
reactor.callWhenRunning(obj.count(obj.timer))
print 'starting...'
reactor.run()
print 'stopped.'
When executed:
$ ./countdown.py
10 ...
Traceback (most recent call last):
File "./countdown.py", line 21, in <module>
reactor.callWhenRunning(obj.count(obj.timer))
File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 666, in callWhenRunning
_callable, *args, **kw)
File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 645, in addSystemEventTrigger
assert callable(_f), "%s is not callable" % _f
AssertionError: None is not callable
I assume I'm not doing something properly in leveraging an object variable; though I'm not sure what I'm doing wrong.
You are calling you callable before passing it in. The returned result of the obj.count() call is not callable.
You need to pass in the method, not the result of calling it:
reactor.callWhenRunning(obj.count, (obj.timer,))
The positional arguments for your method (here just obj.timer) should be given as a separate tuple.
At closer inspection, you don't even need to pass in obj.timer as an argument. You can just access it on self after all, there is no need to pass it in separately:
class countdown(object):
def __init__(self):
self.timer = 0
def count(self):
if self.timer == 0:
reactor.stop()
else:
print self.timer, '...'
self.timer -= 1
reactor.callLater(1, self.count)
and adjust your callWhenRunning() call accordingly:
reactor.callWhenRunning(obj.count)

gearman function in worker remains undefined

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.

Categories