Discussion:
Running Inline::Python in a CGI script
Chris Nighswonger
2013-03-11 15:20:36 UTC
Permalink
I'm trying to use Inline::Python within a CGI script. The script is
run under the latest version of Webmin's miniserv.pl web server.

I have written two very variations of a very simple script.

1. The first version embeds a couple of Python functions in the DATA
portion of the Perl cgi. This version executes fine both from the cli
and as a cgi.

2.The second version imports a class from a Python module. The script
runs fine when called from the cli. However, it borks when executed as
a cgi, complaining of calls to undefined functions/methods. Of course,
those functions/methods are in the Python module.

The only thing I can think might be an issue is the difference in
environment between the shell and the web server. However, a dump of
both environments shows no significant difference, so I'm stumped.

Perl: 5.14.2
Python: 2.7.3
Inline: 0.51
Inline::Python: 0.41
OS: Ubuntu 12.10
Webmin: 1.620

Kind Regards,
Chris
s***@public.gmane.org
2013-03-11 21:21:29 UTC
Permalink
-----Original Message-----
From: Chris Nighswonger
Sent: Tuesday, March 12, 2013 2:20 AM
To: inline-***@public.gmane.org
Subject: Running Inline::Python in a CGI script
Post by Chris Nighswonger
I'm trying to use Inline::Python within a CGI script.
Hi Chris,

Is there anything of relevance in the "Inline CGI" example in
C/C-Cookbook.pod ?

(FAIK, that might be completely irrelevant where Inline::Python is concerned
.... but it does seem feasible to me that the problem could occur because,
in the CGI environment, a needed "read" permission is not provided.)

Cheers,
Rob
Chris Nighswonger
2013-03-12 13:25:40 UTC
Permalink
Hi Rob,

On Mon, Mar 11, 2013 at 5:21 PM, <sisyphus1-sFbbPxZDHXw0n/***@public.gmane.org> wrote:

I'm trying to use Inline::Python within a CGI script.
Post by s***@public.gmane.org
Is there anything of relevance in the "Inline CGI" example in
C/C-Cookbook.pod ?
(FAIK, that might be completely irrelevant where Inline::Python is
concerned .... but it does seem feasible to me that the problem could occur
because, in the CGI environment, a needed "read" permission is not
provided.)
I double checked and .Inline and friends have correct perms. Clearing
everything below .Inline shows that the module is rebuilt as expected on
the next call to the CGI.

I've tried BUILD_NOISY and the other Inline switches which would seem to be
helpful for debug, but with little success at obtaining useful information.
I'm guessing some of that may be largely dependent upon how the author of
Inline::Python has implemented them.

It seems there should be some way to convince inline::Python to fess up to
any errors it is encountering along the way.

Thanks for your help.

Kind Regards,
Chris
Chris Nighswonger
2013-03-12 13:36:01 UTC
Permalink
On Tue, Mar 12, 2013 at 9:25 AM, Chris Nighswonger <
Post by Chris Nighswonger
I double checked and .Inline and friends have correct perms. Clearing
everything below .Inline shows that the module is rebuilt as expected on
the next call to the CGI.
I've tried BUILD_NOISY and the other Inline switches which would seem to
be helpful for debug, but with little success at obtaining useful
information. I'm guessing some of that may be largely dependent upon how
the author of Inline::Python has implemented them.
It seems there should be some way to convince inline::Python to fess up to
any errors it is encountering along the way.
Perhaps I should mention this as well:

The CGI scripts executed by miniserv.pl via an eval of a code block which
sets up the environment and calls up the actual CGI via 'do.' See
https://github.com/webmin/webmin/blob/master/miniserv.pl#L2337 for the
exact code.

I suspected the forced package change on line 2339 might be causing some
scoping problems or some such, so I did this:

***@biblios:/usr/share/webmin/pykota (0.02_pre_alpha *)# perl -e 'package
pyktoa; do "PyKotaConfig.cgi"; die $@ if ($@);'

And get this:

Can't locate object method "new" via package "PykotaConfig" (perhaps you
forgot to load "PykotaConfig"?) at PyKotaConfig.cgi line 33.

This is exactly the same error I receive when running the same script as
CGI. BUT... commenting out line 2339 in miniserve.pl did not fix the
problem. So I suspect there is more to it than that.

Kind Regards,
Chris
Stefan Seifert
2013-03-12 13:43:45 UTC
Permalink
Post by Chris Nighswonger
2.The second version imports a class from a Python module. The script
runs fine when called from the cli. However, it borks when executed as
a cgi, complaining of calls to undefined functions/methods. Of course,
those functions/methods are in the Python module.
Can you post the script code? Or at least the part dealing with Python?
When importing Inline::Python it loads and runs the given Python code
(containing the import statements). Then it inspects the main namespace and
imports those names into the Perl namespace. I suspect that miniserv.pl
trickery leads to namespace problems. So could you please try the
py_new_object() and py_call_function() way of accessing Python? This avoids
namespace magic and should be more reliable:

# create a Python foo.Bar object and make it look like a Bar object in Perl:
my $bar = py_new_object('Bar', 'foo', 'Bar', 'constructor arg 1');
$bar->baz();

Regards,
Stefan
Chris Nighswonger
2013-03-12 13:54:25 UTC
Permalink
Forgot to 'reply all'... sorry.

---------- Forwarded message ----------
From: Chris Nighswonger <cnighswonger-UUNKDCO5ciOWi+***@public.gmane.org>
Date: Tue, Mar 12, 2013 at 9:53 AM
Subject: Re: Running Inline::Python in a CGI script
Post by Stefan Seifert
Post by Chris Nighswonger
2.The second version imports a class from a Python module. The script
runs fine when called from the cli. However, it borks when executed as
a cgi, complaining of calls to undefined functions/methods. Of course,
those functions/methods are in the Python module.
Can you post the script code? Or at least the part dealing with Python?
See the Perl script below. The Python module may be seen here:
http://svn.pykota.com/pykota/trunk/pykota/config.py
Post by Stefan Seifert
When importing Inline::Python it loads and runs the given Python code
(containing the import statements). Then it inspects the main namespace and
imports those names into the Perl namespace. I suspect that miniserv.pl
trickery leads to namespace problems. So could you please try the
py_new_object() and py_call_function() way of accessing Python? This avoids
my $bar = py_new_object('Bar', 'foo', 'Bar', 'constructor arg 1');
$bar->baz();
I'll try this and post back the results.

Kind Regards,
Chris

----------

#!/usr/bin/perl

use strict;
use warnings;

BEGIN {
push(@INC, "..");
};


use Inline Python => 'DATA',
DIRECTORY => '/usr/share/webmin/pykota/.Inline/';

Inline->init();

my $pykota_conf = new PykotaConfig('/etc/pykota/');
print "Admin mail for the AP400N: " . $pykota_conf->getAdminMail('AP400N')
. "\n";

1;

__DATA__
__Python__

from pykota.config import PyKotaConfig as PykotaConfig
Chris Nighswonger
2013-03-12 15:15:40 UTC
Permalink
Post by Stefan Seifert
my $bar = py_new_object('Bar', 'foo', 'Bar', 'constructor arg 1');
$bar->baz();
So here's my shot at this:

use Inline::Python qw( py_new_object );

my $pykota_conf = py_new_object("config", "pykota.config", "PyKotaConfig",
'/etc/pykota/');
print "Admin mail for the AP400N: " . $pykota_conf->getAdminMail('AP400N')
. "\n";

And here's what it says when I execute it at the cli:

***@biblios:/usr/share/webmin/pykota (0.02_pre_alpha *)# ./PyKotaConfig.cgi
'PyKotaConfig' is not a callable object at
/usr/local/lib/perl/5.14.2/Inline/Python.pm line 317.

Keep in mind all of my experience lies with Perl, and I have basically zero
experience with Python, so I may be misunderstanding how Python
packages/classes are referenced.

When I do py_study_package, PyKotaConfig clearly shows up as a class,
though.

Kind Regards,
Christopher
Chris Nighswonger
2013-03-14 11:56:33 UTC
Permalink
On Tue, Mar 12, 2013 at 11:15 AM, Chris Nighswonger <
Post by Chris Nighswonger
use Inline::Python qw( py_new_object );
my $pykota_conf = py_new_object("config", "pykota.config", "PyKotaConfig",
'/etc/pykota/');
print "Admin mail for the AP400N: " . $pykota_conf->getAdminMail('AP400N')
. "\n";
./PyKotaConfig.cgi
'PyKotaConfig' is not a callable object at
/usr/local/lib/perl/5.14.2/Inline/Python.pm line 317.
This call appears to work fine when executed in Python:

***@biblios:/usr/share/webmin/pykota (0.02_pre_alpha *)# python -c 'import
pykota.config; config = pykota.config.PyKotaConfig("/etc/pykota"); print
config.getAdminMail("AP400N");'
foobar-UUNKDCO5ciOWi+***@public.gmane.org
***@biblios:/usr/share/webmin/pykota (0.02_pre_alpha *)#

So is it a syntax problem in my py_new_object call or is it a bug in
Inline::Python?

Kind Regards,
Chris
Stefan Seifert
2013-03-14 12:04:36 UTC
Permalink
Post by Chris Nighswonger
Post by Stefan Seifert
my $bar = py_new_object('Bar', 'foo', 'Bar', 'constructor arg 1');
$bar->baz();
use Inline::Python qw( py_new_object );
my $pykota_conf = py_new_object("config", "pykota.config", "PyKotaConfig",
'/etc/pykota/');
print "Admin mail for the AP400N: " . $pykota_conf->getAdminMail('AP400N')
. "\n";
You're missing the import statement. It's still neccessary for Python to load
the package. Try:

use Inline::Python qw( py_new_object );
use Inline::Python => <<'PYTHON';
import pykota.config
PYTHON

my $pykota_conf = py_new_object("config", "pykota.config", "PyKotaConfig",
'/etc/pykota/');
print "Admin mail for the AP400N: " . $pykota_conf->getAdminMail('AP400N')
. "\n";


Regards,
Stefan
Chris Nighswonger
2013-03-14 14:39:43 UTC
Permalink
Post by Chris Nighswonger
Post by Chris Nighswonger
use Inline::Python qw( py_new_object );
my $pykota_conf = py_new_object("config", "pykota.config",
"PyKotaConfig",
Post by Chris Nighswonger
'/etc/pykota/');
print "Admin mail for the AP400N: " .
$pykota_conf->getAdminMail('AP400N')
Post by Chris Nighswonger
. "\n";
You're missing the import statement. It's still necessary for Python to
load
the package.
That was most of it. Here is what finally worked:

use Inline::Python qw( py_new_object py_call_method );
use Inline Python => 'DATA',
DIRECTORY => '/usr/share/webmin/pykota/.Inline/';

Inline->init();

my $pykota_conf = py_new_object("PyKotaConfig", "pykota.config",
"PyKotaConfig", '/etc/pykota/');

print "Admin mail for the AP400N: " . py_call_method($pykota_conf,
"getAdminMail", 'AP400N') . "\n";

I ended up having to use py_call_method rather than Perl's method syntax.
Maybe I just missed something else about that along the way.

Many thanks to Stefan and Rob for the help and bearing with me.

And thanks for a very cool module which will hopefully save me loads of
execution time over making system calls.

Kind Regards,
Chris

Loading...