Reputation: 689
when I execute this code:
clffunc = sys.argv[1]
def fun(clffunc):
error_vector = clffunc()
print error_vector
loss_total = sum(error_vector)
loss_mean = np.mean(error_vector)
print "The mean error is %.2f" % loss_mean
def svm_clf():
#The clasificator object
clf = svm.SVC()
clf.fit(train_features, train_targets)
# Prediction
test_predicted = clf.predict(test_features)
# Analysis and output
return np.absolute(test_predicted-test_targets)
if __name__ == "__main__":
fun(clffunc)
from the terminal as:
python GraspT.py svm_clf
I get the following error:
File "/home/iki/griper validating/GraspT.py", line 24, in fun
error_vector = clffunc()
TypeError: 'str' object is not callable
In internet I couldn't find a solution. 'str' object is not callable is almost always done when someone redefines a built-in function or something similar. This is not my case. Here I'm passing a string from terminal, and then this is used as a string in a function argument. This argument is in fact a function. So I want to choose the function (a classifier method in machine learning) that is going to be executed in the code.
Upvotes: 1
Views: 4750
Reputation: 19
import sys
def foo(): sys.stdout.write("foo called\n")
def foo1(): sys.stdout.write("foo1 called\n")
if __name__ == "__main__":
if len(sys.argv) < 2: # prevent IndexError
sys.stdout.write("Use commandline argument: foo or foo1\n")
sys.exit() # Print --help and exit
name = sys.argv[1] # Get name (str is)
m = sys.modules["__main__"] # Get main module instance obj
if hasattr(m, name): # Check attribute exists
a = getattr(m, name) # Get attribute by str-name
if hasattr(a, '__call__'): # Verify callable is?
a() # Call
else:
sys.stderr.write("ERROR: is not some callable '%s'\n" % name)
sys.exit(1)
else:
sys.stderr.write("ERROR: has no attr named '%s'\n" % name)
sys.exit(1)
Upvotes: 0
Reputation: 56
The problem is that you don't properly understand what you are trying to accomplish.
clffunc = sys.argv[1]
def fun(clffunc):
error_vector = clffunc()
You are trying to call a string. sys.argv[1]
returns second argument as string. You are doing this : "svm_clf"()
. The simple solution is to use eval
buildin function. For example : eval('%s()' % clffunc)
. this expression will definitely do the job :).
Correction that should make it work :
if __name__ == "__main__":
fun(eval(clffunc))
Upvotes: 0
Reputation: 21
You could directly access the globals
and index by the function's name.
def some_func():
print 'called some_func!'
def some_other_func():
print 'called some_other_func!'
globals()['some_func']()
globals()['some_other_func']()
globals()[sys.argv[1]]()
Also, you could consider using eval.
Upvotes: 0
Reputation: 1124548
svm_clf
is a string, not a function object. The contents of that string may match the name of a function, but that doesn't make it that function.
You could use the a dictionary to map valid names to function:
functions = {'svm_clf': svm_clf}
if __name__ == "__main__":
fun(function[clffunc])
or you could use the dictionary that globals()
returns for that purpose:
if __name__ == "__main__":
fun(globals()[clffunc])
This is probably alright in a command-line tool, but take into account that this allows the user of the tool to make your script call anything with a global name.
Upvotes: 4