I have a class that is called that runs a while loop command prompt, i am using dir()
and getattr()
to dynamically create a list of methods for a command shell. I want to return values, but return from a dynamically called method just exits to main while loop, why how can i fix this?
class myClass :
def __init__(self) :
self.commands = []
for x in dir(self) :
k = getattr( self, x )
if hasattr(k, '__func__') :
self.commands.append(x)
# strips off __init__ and __main__
self.commands = self.commands[2:]
def help(self, args=None) :
for x in self.commands :
####
#### The issue is here
print('Command: {}'.format(x))
f = getattr(self, x)('-h')
desc = f()
print('Description: {}'.format(desc))
...
return SomeValue
def cmd_b(self, args=None) :
if args == '-h' :
return 'Some description'
...
return SomeValue
def cmd_c(self, args=None) :
...
return SomeValue
def __main__(self) :
while True :
command = input(self.ENV['PS1'])
command += ' '
command = command.split()
print(command)
if len(command) > 1 :
print(command)
print(len(command))
args = command[1:]
command = command[0]
else :
command = command[0]
args = None
if command == 'exit' :
break
if command not in dir(self) :
print("Command `{}` not found".format(command))
continue
print(command)
f = getattr( self, command )(args)
x = f()
getattr
and return valuesWhen you do getattr(self, attr)
you get back the corresponding object and it's identical to calling the attribute directly. E.g:
class A:
def __init__(self):
self.v = 42
def func(self):
return "Remember your towel"
a = A()
The following are equivalent
value = a.v
towel = a.func()
value = getattr(a, 'v')
towel = getattr(a, 'func')()
f = getattr(a, 'func')
towel = f()
the variables value
and towels
are 42
and "Remember your towel"
in both cases.
This should respond to your questions.
HOWEVER:
However the main problem in the code has nothing to do with the getattr
.
In the help
method you refer to a f
function that you never define, so that raises an exception.
But the big problem is at the end of __main__
:
except:
pass
at the end. You should never ever do this: you are silencing errors, making it very hard to debug.
If you want to make your code resilient to errors you should catch all the errors and report them somewhere, e.g. using log messages:
import logging
log = logging.getLogger()
# set up the logger
while:
try:
func()
except Exception:
log.exception('my nice message for the user')
If you do somethign like this in your code, it would be much easier to catch errors like the undefined f
function.
In the help
function, you loop over all the commands, help
itself included, and print their help. The way you have implemented the help, this causes an infinite recursion. You should skip calling help
from the help
function.
all the commands return None
or a string. When you will fix the code as indicated above, you will get a lot of errors from line 63: f()
ps: If you are starting with python, give a look at PEP8, the official python style guidelines