How to run python class method at command line - python

I'm trying to connect to a sqllite database using:
class Sqllite_utilities(object):
def __init__(self):
parser = argparse.ArgumentParser()
parser.add_argument("-s","--source", type=str,
help="source table from db")
args = parser.parse_args()
print(args)
source_table= args.source
db_path = "sqlite:///"+settings.SETTINGS_PATH+"\\data.db"
dataset_db = dataset.connect(db_path)
self.dataset_table = dataset_db[source_table]
def missing_ids(self):
for user in self.dataset_table:
print(user['id'])
if __name__ == '__main__':
Sqllite_utilities.missing_ids(sys.argv[1])
When I do:
$ python find_missing_records.py -s test
I get:
Traceback (most recent call last):
File "find_missing_records.py", line 41, in <module>
Sqllite_utilities.missing_ids(sys.argv[1])
TypeError: unbound method missing_ids() must be called with Sqllite_utilities instance as first argument (got str instance instead)
(contact2E)
What am I doing wrong?

When doing:
Sqllite_utilities.missing_ids(sys.argv[1])
you're calling the missing_ids instance method with sys.argv[1] (a string) as self (functional way to call instance methods, but with the wrong object), which explains the error message.
It's clear that you have to create an instance of your object before being able to use the instance methods (the ones without #staticmethod or #classmethod decorators):
if __name__ == '__main__':
s = Sqllite_utilities()
the constructor parses the arguments, using argparse.ArgumentParser which uses sys.argv by default, so leave that aside, it'll work.
Then call your method on the instance:
s.missing_ids()
s is implicitly passed as self when calling missing_ids

As suggested from the top answer to this question: unbound method f() must be called with fibo_ instance as first argument (got classobj instance instead)
Add to your code:
if __name__ == '__main__':
obj = Sqllite_utilities()
s.missing_ids()

Related

Why can't mock.call() accept self as a kwarg?

Background
In python mocking, there is a function assert_has_calls which can verify the order of arguments used to call a function. It has a helper object call which helps validate the arguments.
Problem
Using call(), you cannot pass self as a kwarg. It gives the error: TypeError: __call__() got multiple values for argument 'self'. Why? The workaround is to simply not use self as a kwarg, but I'm afraid there's something fundamental I'm misunderstanding and can't find anything in the documentation that points to it.
Live Code
The code below is pasted here for you to play with: https://repl.it/#artoonie/ObviousIntentReality#main.py
Pasted Code
File 1: test_class.py
needs to be a separate file for mock.patch decorator discoverability
class Class:
def func(self, num):
return num
class Runner:
def run(self):
return Class().func(1)
File 2: test.py
import mock
import test_class
unmockedFunction = test_class.Class.func
class Test:
#mock.patch('test_class.Class.func', autospec=True)
def test_me(self, mocker):
# Make the mock do nothing
mocker.side_effect = unmockedFunction
# Run the function
test_class.Runner().run()
# This works
mocker.assert_called_with(self=mock.ANY, num=1)
# This works
mocker.assert_has_calls([
mock.call(mock.ANY, num=1)
])
# This fails
mocker.assert_has_calls([
mock.call(self=mock.ANY, num=1)
])
Test().test_me()

How to define a custom function of an instance using setattr

I'm trying to add a method to a class dynamically, but I keep running into an error where self is not passed to a the new function. For instance:
class Dummy():
def say_hi(self):
print("hi")
def new_method(self):
print("bye")
dummy = Dummy()
setattr(dummy, "say_bye", new_method)
dummy.say_bye()
results in the following error:
Traceback (most recent call last):
File "main.py", line 13, in <module>
dummy.say_bye()
TypeError: new_method() missing 1 required positional argument: 'self'
What am I doing wrong?
Use types.MethodType feature:
from types import MethodType
class Dummy():
def say_hi(self):
print("hi")
def new_method(self):
print("bye")
dummy = Dummy()
dummy.say_bye = MethodType(new_method, dummy)
dummy.say_bye() # bye
You are setting the function new_method as an attribute of the dummy object.
If you do print(dummy.__dict__) you'll see something like this:
{'say_bye': <function new_method at 0x7fcd949af668>}
This means that your dummy object has the function new_method as an attribute, so when you do dummy.say_bye(), you're calling the function you have as an attribute without any argument.
It is not a function of the Dummy class, it is just a function that your dummy object has as an attribute.
You can achieve the functionality you are looking for using RomanPerekhrest's answer.
Hope it helps.
Cheers!

Using a method from the parent class

I want to call a method from the parent class in a child class.
I use XX.__init__() in my child class and call the press function from the parent class. But it fails when I run the following code:
Func.py
class PC:
def __init__(self):
PCKeyDis = {}
self.PCKeyDis = PCKeyDis
def Press(self,key):
KeyDis = self.PCKeyDis
if len(key)==1 and key.islower():
key = key.upper()
win32api.keybd_event(KeyDis[key],0,0,0)
time.sleep(0.1)
win32api.keybd_event(KeyDis[key],0,win32con.KEYEVENTF_KEYUP,0)
class PCFunc(PC):
def __init__(self):
pass
def Sentence(self,string):
PC.__init__()
strlist = list(string)
for i in xrange(len(strlist)):
if strlist[i] == ' ':
strlist[i] = 'Space'
PC.Press(strlist[i]) #use this function
action.py
import Func
import win32gui
PC = Func.PC()
PCFunc = Func.PCFunc ()
win32gui.SetForegroundWindow(win32gui.FindWindow(winclass,winnm))
PCFunc.Sentence(path)
I get:
unbound method Sentence() must be called with PCFunc instance as first argument (got str instance instead)
If you want to call the constructor of the base class, then you do it on instantiation in the __init__() method, not in the Sentence() method:
def __init__(self):
super(self.__class__, self).__init__()
Since Sentence() is an instance method, you need to call it via an instance of the class (like the error tells you):
pc_func = PCFunc()
pc_func.Sentence(var)
Here you are calling the method with an undefined variable:
PCFunc.Sentence(path)
Instead you need to give a string as parameter, so either write Sentence('path'), or define the variable first:
path = 'my path'
pc_func.Sentence(path)
Do not use the same name as the class name for an instance of the class:
PCFunc = Func.PCFunc ()
Otherwise the variable name storing the instance overwrites the class name.
Apart from that, it is unclear what your code is actually supposed to do. Have a look at the Python code conventions for a first step to making your code more readible. Then do some research about classes and inheritance.
The code you posted does not produce the error you posted. Here is an example that will produce that error:
class Dog:
def do_stuff(self, string):
print string
d = Dog()
d.do_stuff('hello')
Dog.do_stuff(d, 'goodbye')
Dog.do_stuff('goodbye')
--output:--
hello
goodbye
Traceback (most recent call last):
File "1.py", line 9, in <module>
Dog.do_stuff('goodbye')
TypeError: unbound method do_stuff() must be called with Dog instance as first argument (got str instance instead)
An __init__() function can also produce that error:
class Dog:
def __init__(self):
pass
def do_stuff(self, string):
print(string)
Dog.__init__()
--output:--
Traceback (most recent call last):
File "1.py", line 7, in <module>
Dog.__init__()
TypeError: unbound method __init__() must be called with Dog instance as first argument (got nothing instead)
In the line:
d.do_stuff('hello')
the fragment d.do_stuff causes python to create and return a bound method object--which is then immediately executed by the function execution operator () in the fragment ('hello’). The bound method is bound to the instance d, hence the reason it is called a bound method. A bound method automatically passes the instance it contains to the method when the method is executed.
On the other hand, when you write:
Dog.do_stuff(....)
the fragment Dog.do_stuff causes python to create and return an unbound method. An unbound method does not contain an instance, so when an unbound method is executed by the function execution operator (), you must manually pass an instance. (In python3, things changed and you can pass anything as the first argument--an instance of the class isn't required.)

Importing class-type global variables

I'm trying to implement a configuration system contained within a module. The core configuration variable is a class instance and a global variable in this module. It seems that when I import this variable, I cannot use it as a class for some reason.
Consider this minimal example:
foomodule.py:
class FooClass:
number = 5
def bar (self):
return self.number
foo = FooClass
foo.number = 5
main.py
from foomodule import foo
print foo.bar()
Running main.py results in a cryptic error message:
Traceback (most recent call last):
File "main.py", line 2, in <module>
print foo.bar()
TypeError: unbound method bar() must be called with FooClass instance as first argument (got nothing instead)
But I am calling it with a FooClass instance which I'd think should be the self argument like it usually is. What am I doing wrong here?
You only bound foo to the class; you didn't make it an instance:
foo = FooClass # only creates an additional reference
Call the class:
foo = FooClass() # creates an instance of FooClass
In Python you usually don't use accessor methods; just reference foo.number in your main module, rather than use foo.bar() to obtain it.
In your example foo is just an alias for FooClass. I assume that your actual problem is more complicated than your snippet. However, if you really need a class method, you can annotate it with #classmethod decorator.
class FooClass(object):
number = 5
#classmethod
def bar(cls):
return cls.number
To use your the class you could do:
from foomodule import Foo
Foo.bar()
Or you can access the class member directly
Foo.number

"<method> takes no arguments (1 given)" but I gave none [duplicate]

This question already has answers here:
"TypeError: method() takes 1 positional argument but 2 were given" but I only passed one
(10 answers)
Closed 6 months ago.
I am new to Python and I have written this simple script:
#!/usr/bin/python3
import sys
class Hello:
def printHello():
print('Hello!')
def main():
helloObject = Hello()
helloObject.printHello() # Here is the error
if __name__ == '__main__':
main()
When I run it (./hello.py) I get the following error message:
Traceback (most recent call last):
File "./hello.py", line 13, in <module>
main()
File "./hello.py", line 10, in main
helloObject.printHello()
TypeError: printHello() takes no arguments (1 given)
Why does Python think I gave printHello() an argument while I clearly did not? What have I done wrong?
The error is referring to the implicit self argument that is passed implicitly when calling a method like helloObject.printHello(). This parameter needs to be included explicitly in the definition of an instance method. It should look like this:
class Hello:
def printHello(self):
print('Hello!')
If you want printHello as instance method, it should receive self as argument always(ant python will pass implicitly) Unless you want printHello as a static method, then you'll have to use #staticmethod
#!/usr/bin/python3
import sys
class Hello:
def printHello(self):
print('Hello!')
def main():
helloObject = Hello()
helloObject.printHello() # Here is the error
if __name__ == '__main__':
main()
As '#staticmethod'
#!/usr/bin/python3
import sys
class Hello:
#staticmethod
def printHello():
print('Hello!')
def main():
Hello.printHello() # Here is the error
if __name__ == '__main__':
main()
Calling a method on the instance of an object returns the object itself (usually self) to the object. For example, calling Hello().printHello() is the same as calling Hello.printHello(Hello()), which uses an instance of a Hello object as the first argument.
Instead, define your printHello statement as def printHello(self):

Categories

Resources