getattr and method name

K

Kevin Walzer

I'm seeing a very odd error in an application I'm developing using
Python 2.7.2, on Mac OS 10.7.

This application uses a wrapper method to look up other method names via
getattr and then call those methods. I have not previously had an issue
with this name, but for some reason this functionality no longer works
as expected.

Here is the relevant code:

#run command with root privileges
def runCommand(self, cmd, *args):
try:
functionstring = args[2]
callfunction = getattr(self, functionstring.split('.')[1])
self.passtext = self.tk.call('authorize::getAuthPassword')
callfunction()
except:
try:
print cmd
functionstring = cmd.split()[2]
callfunction = getattr(self, functionstring.split('.')[1])
self.passtext = self.tk.call('authorize::getAuthPassword')
callfunction()
except:
raise

I use this approach to call the method named in the "cmd" parameter
because I also have to look up a password name that is returned by an
underlying Tk package that I use in my application (that's the reason
for the 'self.tk.call'). What is happening is when I use the
"callfunction()" call, instead of the method name being called, a string
like this is being invoked:

<bound method phynchronicityApp.scanPackages of
<__main__.phynchronicityApp instance at 0x101b232d8>>

The "scanPackages" method (just to use it as an example) uses Popen to
call an underlying system tool on the OS. However, when invoked via
callfunction(), the 'bound method...' string is passed to the OS instead
as a command! As a result, I get this output from the pipe:

/bin/sh: bound: No such file or directory

I am not sure what in my application is causing this kind of breakage,
as earlier versions of the app ran fine with similar code on earlier
versions on the OS. Is this the correct way to structure this kind of
functionality, or am I better off structuring it some other way?

--Kevin
 
C

Chris Rebert

I'm seeing a very odd error in an application I'm developing using Python
2.7.2, on Mac OS 10.7.

This application uses a wrapper method to look up other method names via
getattr and then call those methods. I have not previously had an issue with
this name, but for some reason this functionality no longer works as
expected.

Here is the relevant code:

   #run command with root privileges
   def runCommand(self, cmd, *args):
       try:
           functionstring = args[2]
           callfunction = getattr(self, functionstring.split('.')[1])
           self.passtext = self.tk.call('authorize::getAuthPassword')
           callfunction()
       except:
           try:
               print cmd
               functionstring =cmd.split()[2]
               callfunction = getattr(self, functionstring.split('.')[1])
               self.passtext = self.tk.call('authorize::getAuthPassword')
               callfunction()
           except:
               raise

I use this approach to call the method named in the "cmd" parameter because
I also have to look up a password name that is returned by an underlying Tk
package that I use in my application (that's the reason for the
'self.tk.call'). What is happening is when I use the "callfunction()" call,
instead of the method name being called, a string like this is being
invoked:

<bound method phynchronicityApp.scanPackages of <__main__.phynchronicityApp
instance at 0x101b232d8>>

Er, your terminology seems kinda funky. Do you mean to say that
repr(callfunction) results in that string (which is normal and
expected), or that the return value from callfunction() is that string
(which would be rather bizarre)? I would presume the former. [One does
not call/invoke a string; strings aren't callable.]
The "scanPackages" method (just to use it as an example) uses Popen to call
an underlying system tool on the OS. However, when invoked via
callfunction(), the 'bound method...' string is passed to the OS instead as
a command! As a result, I get this output from the pipe:

/bin/sh: bound: No such file or directory

Either you've elided some important part of the code from your
fragment above, or the problem would seem to lie in scanPackages()
[presumably its Popen() call is screwy]. Please post the code for
scanPackages(), and (if applicable) the full code for runCommand().

Cheers,
Chris
 
T

Terry Reedy

I'm seeing a very odd error in an application I'm developing using
Python 2.7.2, on Mac OS 10.7.

This application uses a wrapper method to look up other method names via
getattr and then call those methods. I have not previously had an issue
with this name, but for some reason this functionality no longer works
as expected.

Here is the relevant code:

#run command with root privileges
def runCommand(self, cmd, *args):
try:
functionstring = args[2]
callfunction = getattr(self, functionstring.split('.')[1])
self.passtext = self.tk.call('authorize::getAuthPassword')
callfunction()
except:
try:
print cmd
functionstring = cmd.split()[2]
callfunction = getattr(self, functionstring.split('.')[1])
self.passtext = self.tk.call('authorize::getAuthPassword')
callfunction()
except:
raise

I use this approach to call the method named in the "cmd" parameter
because I also have to look up a password name that is returned by an
underlying Tk package that I use in my application (that's the reason
for the 'self.tk.call'). What is happening is when I use the
"callfunction()" call, instead of the method name being called, a string
like this is being invoked:

<bound method phynchronicityApp.scanPackages of
<__main__.phynchronicityApp instance at 0x101b232d8>>

The "scanPackages" method (just to use it as an example) uses Popen to
call an underlying system tool on the OS. However, when invoked via
callfunction(), the 'bound method...' string is passed to the OS instead
as a command! As a result, I get this output from the pipe:

/bin/sh: bound: No such file or directory

I am not sure what in my application is causing this kind of breakage,
as earlier versions of the app ran fine with similar code on earlier
versions on the OS. Is this the correct way to structure this kind of
functionality, or am I better off structuring it some other way?

I do not know of any 2.7 changes that would affect such code. Perhaps
you changed something in the method being invoked (not shown)
..
You did not specify whether you have the problem in the first or second
try block. I would start with printing the type and value of some to all
of the variables.
 
S

Steven D'Aprano

I'm seeing a very odd error in an application I'm developing using
Python 2.7.2, on Mac OS 10.7.

This application uses a wrapper method to look up other method names via
getattr and then call those methods. I have not previously had an issue
with this name, but for some reason this functionality no longer works
as expected.

Here is the relevant code:

#run command with root privileges
def runCommand(self, cmd, *args):
try:
functionstring = args[2]
callfunction = getattr(self, functionstring.split('.')[1])
self.passtext = self.tk.call('authorize::getAuthPassword')
callfunction()
except:

Bare excepts should almost never be used. I'd say they certainly
shouldn't be used like this: you can mask coding bugs, user
KeyboardInterrupts, and other things which shouldn't be masked.

It also obscures the intent of the code. As far as I can see, it appears
that this method expects to be called like this:

instance.runCommand(cmd, some, arbitrary, number, of, extra, args)

In this case, the method tries to authenticate and then execute some
command based on "number" (but ignoring all other arguments, including
cmd); if ANY failure occurs at all, including too few arguments, missing
dot in the argument, or failed authentication(?), then try again using
"cmd" instead. I don't understand the intent of this code.

try:
print cmd
functionstring = cmd.split()[2]
callfunction = getattr(self,
functionstring.split('.')[1])
self.passtext = self.tk.call(
'authorize::getAuthPassword')
callfunction()
except:
raise

This try block is completely unnecessary. What's the point of catching an
exception only to immediately raise it again?


I use this approach to call the method named in the "cmd" parameter
because I also have to look up a password name that is returned by an
underlying Tk package that I use in my application (that's the reason
for the 'self.tk.call').

What's a password name? Generally passwords don't have names themselves.
Do you mean a user or account name?

What is happening is when I use the
"callfunction()" call, instead of the method name being called, a string
like this is being invoked:

<bound method phynchronicityApp.scanPackages of
<__main__.phynchronicityApp instance at 0x101b232d8>>


Are you sure that's meant to be a string? It appears to be an actual
bound method. What makes you think it is a string? Where is that output
coming from?

My *guess* is that this is the output of the "print cmd" line. If so,
that tells you nothing about the type of cmd. It does however tell you
that you need to look at what is calling the runCommand method. Why is it
being called with a method as the command? What should it be called with?
Given that you call cmd.split()[2], I would expect that cmd should be a
string with at least three words.

Taking a wild guess, perhaps you should call cmd to get a string which
then gets split into pieces to get the name of the system tool you are
expecting:

The "scanPackages" method (just to use it as an example) uses Popen to
call an underlying system tool on the OS. However, when invoked via
callfunction(), the 'bound method...' string is passed to the OS instead
as a command! As a result, I get this output from the pipe:

/bin/sh: bound: No such file or directory


Or possibly the error is in callfunction. What does it do?

I am not sure what in my application is causing this kind of breakage,
as earlier versions of the app ran fine with similar code on earlier
versions on the OS. Is this the correct way to structure this kind of
functionality, or am I better off structuring it some other way?

Frankly, it looks like a mess. But I don't understand your intention well
enough to make any recommendations.
 
K

Kevin Walzer

Turns out the error was a typo in the actual method being
called...*faceinhands*

Sorry for the noise.
 
R

Roy Smith

Gary Herron said:
But this is a great example of why you should not use a naked except
clause. As stated, your code will execute the except clause for *any*
kind of an error, not just the exception you envisioned when you wrote
it. If you had written the except clause to catch just the exceptions
you were interested in, then the exception int a called function would
have come through that code as in un-handled exception, instead of being
caught and essentially ignored.

And, along those same lines, a couple of bits of generic exception
advice...

1) Create specific exceptions to describe specific problems.
FooPackageSocketBindError sure beats IOError when it comes to trying to
figure out what went wrong.

2) As much as possible, keep your try blocks short. In the original
example, we've got:

try:
functionstring = args[2]
callfunction = getattr(self, functionstring.split('.')[1])
self.passtext = self.tk.call('authorize::getAuthPassword')
callfunction()

If we caught an IndexError, we would not know if it came from the
args[2], or the getattr(...)[1], or possibly even from something deep
down within callfunction().
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,150
Members
46,696
Latest member
BarbraOLog

Latest Threads

Top