Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python string as file argument to subprocess

I am trying to pass a file to a program (MolPro) that I start as subprocess with Python.

It most commonly takes a file as argument, like this in console:

path/molpro filename.ext

Where filename.ex contains the code to execute. Alternatively a bash script (what I'm trying to do but in Python):

#!/usr/bin/env bash
path/molpro << EOF
    # MolPro code
EOF

I'm trying to do the above in Python. I have tried this:

from subprocess import Popen, STDOUT, PIPE
DEVNULL = open('/dev/null', 'w')  # I'm using Python 2 so I can't use subprocess.DEVNULL
StdinCommand = '''
    MolPro code
'''

# Method 1 (stdout will be a file)
Popen(['path/molpro', StdinCommand], shell = False, stdout = None, stderr = STDOUT, stdin = DEVNULL)
# ERROR: more than 1 input file not allowed

# Method 2
p = Popen(['path/molpro', StdinCommand], shell = False, stdout = None, stderr = STDOUT, stdin = PIPE)
p.communicate(input = StdinCommand)
# ERROR: more than 1 input file not allowed

So I am pretty sure the input doesn't look enough like a file, but even looking at Python - How do I pass a string into subprocess.Popen (using the stdin argument)? I can't find what Im doing wrong.

I prefer not to:

  • Write the string to an actual file
  • set shell to True
  • (And I can't change MolPro code)

Thanks a lot for any help!

Update: if anyone is trying to do the same thing, if you don't want to wait for the job to finish (as it doesn't return anything, either way), use p.stdin.write(StdinCommand) instead.

like image 439
Mark Avatar asked Feb 17 '12 19:02

Mark


People also ask

How can we avoid shell true in subprocess?

From the docs: args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names).

What is Popen in Python?

Python method popen() opens a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'. The bufsize argument has the same meaning as in open() function.

What is Close_fds in subprocess?

I suspect that close_fds solves the problem of file descriptors leaking to subprocesses. Imagine opening a file, and then running some task using subprocess . Without close_fds , the file descriptor is copied to the subprocess, so even if the parent process closes the file, the file remains open due to the subprocess.


1 Answers

It seems like your second method should work if you remove StdinCommand from the Popen() arguments:

p = Popen(['/vol/thchem/x86_64-linux/bin/molpro'], shell = False, stdout = None, stderr = STDOUT, stdin = PIPE)
p.communicate(input = StdinCommand)
like image 130
Andrew Clark Avatar answered Sep 21 '22 10:09

Andrew Clark