Colin Murphy
Colin Murphy

Reputation: 1155

Python Popen input from variable?

I am trying to use Popen to run a java program that takes a few arguments, the last of them is a xml template.

What I have so far attempts to pass the value of the template through communicate(), but it doesn't seem to work.

command = [
        'java',
        '-jar',
        '~/jenkins-cli.jar',
        '-noKeyAuth',
        '-s',
        'docker-host',
        'create-job',
        (self.project.project_name+'-'+env)
    ]

subprocess.Popen(command,
                 stdin=subprocess.PIPE,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE
                 ).communicate(input=template.render(template_vars))

I know for a fact that the value of template.render(template_vars) is correct, I can use the output from that function call on the command line and it works perfectly, the issue is only in passing the value to the process.

If I run the following from the command line everything works.

java -jar ~/jenkins-cli.jar -noKeyAuth -s jenkins-host create-job test-dev < template.xml

Is there a better way to send the output of template.render(template_vars) as input to the process?

Upvotes: 0

Views: 472

Answers (1)

abarnert
abarnert

Reputation: 365975

I don't think your problem is the input here, but rather the arguments. In particular:

'~/jenkins-cli.jar',

On the command line, you get shell tilde expansion for free. But when using subprocess (or calling exec-family functions from any language, as subprocess does), you have to do it manually, like this:

os.path.expanduser('~/jenkins-cli.jar'),

Also, you're passing a different value for the -s option ('docker-host' instead of 'jenkins-host'), and for the project name ('something-env' instead of 'test-dev'), so the fact that the command line works doesn't really show that your code should work.


As a side note, if you're trying to debug your code, ignoring the stdout, stderr, and return code seems pretty silly. Print them out and see what you get, like this:

p = Popen(command, …)
out, err = p.communicate(input=…)
print(p.returncode, out, err)

Or, of course, don't capture the stdout and stderr in the first place, so they just print to the console.

Upvotes: 2

Related Questions