views:

1340

answers:

5

I'm hacking some support for DomainKeys and DKIM into an open source email marketing program, which uses a python script to send the actual emails via SMTP. I decided to go the quick and dirty route, and just write a perl script that accepts an email message from STDIN, signs it, then returns it signed.

What I would like to do, is from the python script, pipe the email text that's in a string to the perl script, and store the result in another variable, so I can send the email signed. I'm not exactly a python guru, however, and I can't seem to find a good way to do this. I'm pretty sure I can use something like os.system for this, but piping a variable to the perl script is something that seems to elude me.

In short: How can I pipe a variable from a python script, to a perl script, and store the result in Python?

EDIT: I forgot to include that the system I'm working with only has python v2.3

+3  A: 

os.popen() will return a tuple with the stdin and stdout of the subprocess.

Sii
popen has been deprecated since version 2.6, you should use subprocess instead.
Chas. Owens
-1: deprecated. Use the subprocess module.
nosklo
From the question: "only has python v2.3 " deprecated hasn't happened yet.
S.Lott
This worked pretty well. I ended up using popen2, opening a input and output, which worked like a charm. Thanks for the help.
Alex Fort
+2  A: 

"I'm pretty sure I can use something like os.system for this, but piping a variable to the perl script is something that seems to elude me."

Correct. The subprocess module is like os.system, but provides the piping features you're looking for.

S.Lott
I should have clarified that I'm only working with python 2.3, and it seems the subprocess module is for 2.4 and up.
Alex Fort
@Alex Fort: Just grab the subprocess module from 2.4 and run it on 2.3. It seems to work.
nosklo
+2  A: 
from subprocess import Popen, PIPE
p = Popen(['./foo.pl'], stdin=PIPE, stdout=PIPE)
p.stdin.write(the_input)
p.stdin.close()
the_output = p.stdout.read()
ngn
+2  A: 

I'm sure there's a reason you're going down the route you've chosen, but why not just do the signing in Python?

How are you signing it? Maybe we could provide some assitance in writing a python implementation?

Jon Cage
I *would* do the signing from python, but my python-fu is pretty weak. That would be a more optimal solution, however, so I may consider that in the future, especially if I decide to contribute the code to the community.
Alex Fort
If you post the Perl solution somewhere I'd be happy to help try and convert it :-)
Jon Cage
The Perl solution is really simple. I'm just taking advantage of the Mail::DKIM module, which makes signing an email pretty trivial.
Alex Fort
So something like this should make a Python implementation similarly trivial:http://hewgill.com/pydkim/:-)
Jon Cage
...ah, except it requires Python >= 2.5 ...rats! Out of curiosity, why are you still using 2.3 not a more recent build?
Jon Cage
I made some changes to pydkim so that it will operate in a degraded mode under Python 2.4, see the latest code on github: http://github.com/ghewgill/pydkim/tree/master (otherwise unreleased). It might be possible to also make it work under Python 2.3 but significantly more changes may be necessary.
Greg Hewgill
I'm just using 2.3 because that's what came installed on my RHEL 4 install. I'm not sure what could possibly break if I upgrade, so I've been putting that off, and since RHEL 4 repos contain 2.3, it'll probably have to compile from source to get something like 2.5 working. It's probably worth the trouble to get it upgraded, however.
Alex Fort
@Alex Fort: Most of my machines have two or more versions of Python installed. Generally, Python is pretty good about multiple versions coexisting, all the files go into /usr/local/lib/python2.x with the version as appropriate. Then the one binary goes into /usr/local/bin/python2.x, and /usr/local/bin/python is hardlinked to whatever version you want to be the default. You can then run "python test.py" for the default version or something "python2.4 test.py" for a specific version.
Greg Hewgill
+3  A: 

Use subprocess. Here is the Python script:

#!/usr/bin/python

import subprocess

var = "world"

pipe = subprocess.Popen(["./x.pl", var], stdout=subprocess.PIPE)

result = pipe.stdout.read()

print result

And here is the Perl script:

#!/usr/bin/perl

use strict;
use warnings;

my $name = shift;

print "Hello $name!\n";
Chas. Owens
According to the question, the Perl script should accept input, not an arg.
ngn