I am trying to learn a bit about threading by building some code that will maintain a list and eventually send values from that list to a to-be-created function. When I call QueryReport.add I get the error TypeError: add() missing 1 required positional argument: 'user'. I am trying to pass in report and user list values. It is my belief the add method needs self but that self for some reason seems to be throwing off the call I made because now I dont have the right number of positional aruguments. In many other code examples I see methods defined with self and two other values with the idea that when the mthod is called two values are passed. Any thoughts on what I am doing wrong? Since I cant get past this syntax error, is there anything else as blantly wrong?
from threading import *
class QueueReport(Thread):
def __init__(self):
Thread.__init__(self)
self.reports_to_call = []
def add(self, report, user):
self.reports_to_call.append([report, user])
print("Added Value")
def run(self):
print("Running")
#print(reports_to_call)
#will loop and send values from this list to another function
if __name__ == '__main__':
t1 = QueueReport()
t1.run()
QueueReport.add("mainreport", "user")
You are attempting to add to the class QueueReport instead of the instance of the class t1. When you call the function on the class, there is no self so it treats "mainreport" as self and "user" as report.
What you want to do is t1.add("mainreport", "user").
The wrinkle is, if run is an infinite loop it will block execution and t1.add will never happen.
What you can do is create a separate thread for t1.run.
from threading import Thread
thread = Thread(target=t1.run)
thread.start()
t1.add("mainreport", "user")
Edit: silly me, I did not see that you were already using threading.
You are using the Class method instead of using the instantiation of the class.
Because of that, self is not given to the method, hence missing a parameter.
Try doing t1.add("mainreport", "user")
Related
I'm relatively new in python and I have the following question, my code looks something like this:
class Hkprop:
def hkprop_f(self):
hkprop= self.Mkprop().fun2() + self.Fkprop().fun4()
return hkprop
class Fkprop:
def fun1(self):
#something
def fun2(self):
self.fun1()
class Mkprop:
def fun3(self):
#something
def fun4(self):
self.fun1() #here I want to call fun1 but I don't know if it is possible or how to do it
I know this might be a super basic question, but if someone could help me I would really appreaciate it. I've been looking and came across #staticmethod, but I didn't completely understand. Is there a way of calling the function without using it?
If you want to call fun1, you can do Hkprop.Fkprop.fun1()
Yes, this is basic but sometimes, even such basic questions takes a little time to figure it out. So, I am assuming that your indentations are correct, and you have nested classes. Here is the solution that I did.... Hope this is helpful to you...
You will need to use the class inheritance methodolody, or simply learn how to instantiate class objects from one class to another as shown below.
When you save this code to a file a run it. You will see that first it will instantiate Hkprop.Mkprop and the call fun4. The next thing, we have done is instantiate Hkprop.Fkprop in func4 to be able to call func1 in FKprop class.
class Hkprop:
def hkprop_f(self):
hkprop= self.Mkprop().fun2() + self.Fkprop().fun4()
return hkprop
class Fkprop:
def fun1(self):
print('I just called this function')
def fun2(self):
self.fun1()
class Mkprop:
def fun3(self):
print('this is soemthing')
def fun4(self):
fk = Hkprop.Fkprop()
fk.fun1()
if __name__ == '__main__':
mk = Hkprop.Mkprop()
mk.fun4()
Let's breakdown your code. You wrote:
def fun4(self):
self.fun1()
There are 2 problems here.
self represents the instance of the class. Since, Mkprop class has no defintion of fun1() so it cannot access fun1()
fun1() function also expects a parameter in Fkprop class
In fun4, if you want to call fun1() then make the following change:
def fun4(self):
Hkprop.Fkprop.fun1(self)
Moreover, in python, functions cannot have empty body. Your current code will get the error:
IndentationError: expected an indented block
Because the interpreter expects a function body that is indented. To keep the empty functions, change fun1 & fun3 functions like this
def fun1():
pass
def fun3():
pass
pass is a special statement in Python that does nothing. It only works as a dummy statement.
I never tried nested classes before. In your case, it seems like you're calling a nonexistent function from a class. fun1() does not exist in class Mkprop.
If you want to call fun1(), you have to call it from it's respective class, therefore, Hkprop().Fkprop().fun1(). It goes something like this: Parent Class -> Sub class -> Function.
I have a method like this in Python :
def test(a,b):
return a+b, a-b
How can I run this in a background thread and wait until the function returns.
The problem is the method is pretty big and the project involves GUI, so I can't wait until it's return.
In my opinion, you should besides this thread run another thread that checks if there is result. Or Implement callback that is called at the end of the thread. However, since you have gui, which as far as I know is simply a class -> you can store result into obj/class variable and check if the result came.
I would use mutable variable, which is sometimes used. Lets create special class which will be used for storing results from thread functions.
import threading
import time
class ResultContainer:
results = [] # Mutable - anything inside this list will be accesable anywher in your program
# Lets use decorator with argument
# This way it wont break your function
def save_result(cls):
def decorator(func):
def wrapper(*args,**kwargs):
# get result from the function
func_result = func(*args,**kwargs)
# Pass the result into mutable list in our ResultContainer class
cls.results.append(func_result)
# Return result from the function
return func_result
return wrapper
return decorator
# as argument to decorator, add the class with mutable list
#save_result(ResultContainer)
def func(a,b):
time.sleep(3)
return a,b
th = threading.Thread(target=func,args=(1,2))
th.daemon = True
th.start()
while not ResultContainer.results:
time.sleep(1)
print(ResultContainer.results)
So, in this code, we have class ResultContainer with list. Whatever you put in it, you can easily access it from anywhere in the code (between threads and etc... exception is between processes due to GIL). I made decorator, so you can store result from any function without violating the function. This is just example how you can run threads and leave it to store result itself without you taking care of it. All you have to do, is to check, if the result arrived.
You can use global variables, to do the same thing. But I dont advise you to use them. They are ugly and you have to be very careful when using them.
For even more simplicity, if you dont mind violating your function, you can just, without using decorator, just push result to class with list directly in the function, like this:
def func(a,b):
time.sleep(3)
ResultContainer.results.append(tuple(a,b))
return a,b
I'm an experienced programmer, but completely new to Python.
I've resolved most difficulties, but I can't get the queue module to work.
Any help gratefully received. Python 3.2.
Reduced to its basic minimum, here's the issue:
>>>import queue
>>>q = queue.Queue
>>>q.qsize()
Traceback:
...
q.qsize()
...
TypeError: qsize() takes 1 argument exactly (0 given)
Documentation...
7.8.1. Queue Objects
Queue objects (Queue, LifoQueue, or PriorityQueue) provide the public methods described below.
Queue.qsize()
OK - what argument.... ?
You're not initializing an instance, you're just reassigning the class name to q. The "argument" that it's talking about is self, the explicit self-reference that all Python methods need. In other words, it's saying that you're trying to call an instance method with no instance.
>>> q = queue.Queue()
>>> q.qsize()
If you've never seen a Python method definition, it looks something like this:
class Queue(object):
# Note the explicit 'self' argument
def qsize(self):
# ...
You are simply renaming queue.Queue and not instantiating an object.
Try this
q = queue.Queue()
print q.qsize()
Only one argument is passed. Still I'm getting error that 2 arguments have been passed. head and tail are not being initialized to -1.
class Queue_demo:
head=-1
tail=-1
a=[]
def enqueue(data=10):
if(head==-1 and tail==-1):
head=head+1
tail=tail+1
a.append(data)
else:
tail=tail+1
a.append(data)
def dequeue():
y=a[head]
if(head==tail):
head,tail=-1,-1
else:
head=head+1
return y
q1=Queue_demo()
q2=Queue_demo()
q1.enqueue(12)
while(q1.tail==-1):
print(q1.dequeue())
There are a few issues with your code.
The one that is directly causing your error is that you have not given your methods a self argument. When you call q1.enqueue(12) Python translates this to Queue_demo.enqueue(q1, 12). The object the method is being called on is passed to the method as the first argument. By convention, it is usually named self.
This leads me to the second issue you're going to encounter once you get past the wrong number of arguments error. Your instances are going to all be sharing the same set of data members, since they're currently accessing class variables head, tail and a, rather than instance variables. This will be very confusing, as adding an item to one queue will make it appear in all other queues too.
To fix this, what you will want to do is create those variables in a constructor (which is simply a method named __init__), rather than defining them in the class definition. Here's what your __init__ method will probably look like:
def __init__(self):
self.head = -1
self.tail = -1
self.a = []
Remember that Python is often different from other programming languages! You don't need to declare your member variables, just start assigning things as values on self and you'll be all set.
I've got a question about defining functions and the self-parameter in python.
There is following code.
class Dictionaries(object):
__CSVDescription = ["ID", "States", "FilterTime", "Reaction", "DTC", "ActiveDischarge"]
def __makeDict(Lst):
return dict(zip(Lst, range(len(Lst))))
def getDict(self):
return self.__makeDict(self.__CSVDescription)
CSVDescription = __makeDict(__CSVDescription)
x = Dictionaries()
print x.CSVDescription
print x.getDict()
x.CSVDescription works fine. But print x.getDict() returns an error.
TypeError: __makeDict() takes exactly 1 argument (2 given)
I can add the self-parameter to the __makeDict() method, but then print x.CSVDescription wouldn't work.
How do I use the self-parameter correctly?
In python, the self parameter is implicitly passed to instance methods, unless the method is decorated with #staticmethod.
In this case, __makeDict doesn't need a reference to the object itself, so it can be made a static method so you can omit the self:
#staticmethod
def __makeDict(Lst): # ...
def getDict(self):
return self.__makeDict(self.__CSVDescription)
A solution using #staticmethod won't work here because calling the method from the class body itself doesn't invoke the descriptor protocol (this would also be a problem for normal methods if they were descriptors - but that isn't the case until after the class definition has been compiled). There are four major options here - but most of them could be seen as some level of code obfuscation, and would really need a comment to answer the question "why not just use a staticmethod?".
The first is, as #Marcus suggests, to always call the method from the class, not from an instance. That is, every time you would do self.__makeDict, do self.__class__.__makeDict instead. This will look strange, because it is a strange thing to do - in Python, you almost never need to call a method as Class.method, and the only time you do (in code written before super became available), using self.__class__ would be wrong.
In similar vein, but the other way around, you could make it a staticmethod and invoke the descriptor protocol manually in the class body - do: __makeDict.__get__(None, Dictionaries)(__lst).
Or, you could detect yourself what context its being called from by getting fancy with optional arguments:
def __makeDict(self, Lst=None):
if Lst is None:
Lst = self
...
But, by far the best way is to realise you're working in Python and not Java - put it outside the class.
def _makeDict(Lst):
...
class Dictionaries(object):
def getDict(self):
return _makeDict(self.__CSVDescription)
CSVDescription = _makeDict(__CSVDescription)