Discussion:
Accessing Perl Hash Attributes from Python Object
Ry
2012-04-14 13:48:54 UTC
Permalink
Hi again, been using this great software for awhile now. One thing I can't
figure out though is how to access the hash attributes of a Perl object
from within Python. For example, I have a "Pythonized" Perl subroutine
called Player() that returns an object that has an attribute 'name'
(accessed in Perl using $object->{name}). So in Python, I do 'player =
Player(0)'. How do you get the 'name' attribute?

The Perl version of the Player() subroutine was not created by me, and is
part of another library. I'm using Inline::Python from within a plugin that
is loaded into a application using that library, so I can't modify the
subroutine. I could try to create a subclass of the class returned by
Player() and add a __getattr__() subroutine to it, but that seems too
hackish. I'm trying to use Python as much as possible.

BTW, I got the subroutine by doing something like Player =
perl.eval('\&Player'). I do the same kind of thing to get other objects,
like object = perl.eval('\@array'). Is there a better way to do this?
Inline::Python does not seem to allow the use of other perlmodule functions
such as perl.callm().

Thanks,
Ryan
Stefan Seifert
2012-04-17 15:13:32 UTC
Permalink
Post by Ry
Hi again, been using this great software for awhile now. One thing I can't
figure out though is how to access the hash attributes of a Perl object
from within Python. For example, I have a "Pythonized" Perl subroutine
called Player() that returns an object that has an attribute 'name'
(accessed in Perl using $object->{name}). So in Python, I do 'player =
Player(0)'. How do you get the 'name' attribute?
The Perl version of the Player() subroutine was not created by me, and is
part of another library. I'm using Inline::Python from within a plugin that
is loaded into a application using that library, so I can't modify the
subroutine. I could try to create a subclass of the class returned by
Player() and add a __getattr__() subroutine to it, but that seems too
hackish. I'm trying to use Python as much as possible.
Inline::Python's main use case is for accessing Python libraries or legacy
code from Perl programs, not the other way round. So the assumption is that
it's somewhat easy to change the Perl code. That's why for accessing a Perl
object's attributes from Python code the object has to support a __getattr__
method.

That being said and even though it's bad style to access an object's innards
like that instead of going through accessor methods, I guess it would still be
worthwhile to support this case. I think I could extend the PerlObj_getattr
function with a fallback in case no __getattr__ method was found.

I'm a bit low on time, so if you want to write a couple of lines of C, I'd be
happy to take a patch. Otherwise I'll see if I can push it somewhere into my
schedule.
Post by Ry
BTW, I got the subroutine by doing something like Player =
perl.eval('\&Player'). I do the same kind of thing to get other objects,
Inline::Python does not seem to allow the use of other perlmodule functions
such as perl.callm().
For functions it's quite easy: perl.foo() calls the foo sub in the main::
namespace. You can get a reference like with any Python function:
foo = perl.foo;
foo();

Functions in other packages are just the same. To access Foo::Bar::test use:
ref_to_test = perl.Foo.Bar.test;

Since constructors are just functions in Perl, you can use them to create
objects:
foo = perl.Foo.new()

Accessing variables is not as simple. A very non-hackish way would just be to
define Perl functions which return those variables. Like:
my @array;
sub get_array { return \@array; }
Note that unlike pyperl, such a reference does not get wrapped in
Inline::Python but the data will be copied into a similiar data structure in
Python. So changes on either side will not propagate after the copy. Objects
behave better in this regard.

Regards,
Stefan

Loading...