Passing input to an executable using Python subprocess module - bash

I have an input file called 0.in. To get the output I do ./a.out < 0.in in the Bash Shell.
Now, I have several such files (more than 500) and I want to automate this process using Python's subprocess module.
I tried doing this:
data=subprocess.Popen(['./a.out','< 0.in'],stdout=subprocess.PIPE,stdin=subprocess.PIPE).communicate()
Nothing was printed (data[0] was blank) when I ran this. What is the right method to do what I want to do?

Redirection using < is a shell feature, not a python feature.
There are two choices:
Use shell=True and let the shell handle redirection:
data = subprocess.Popen(['./a.out < 0.in'], stdout=subprocess.PIPE, shell=True).communicate()
Let python handle redirection:
with open('0.in') as f:
data = subprocess.Popen(['./a.out'], stdout=subprocess.PIPE, stdin=f).communicate()
The second option is usually preferred because it avoids the vagaries of the shell.
If you want to capture stderr in data, then add stderr=subprocess.PIPE to the Popen command. Otherwise, stderr will appear on the terminal or wherever python's error messages are being sent.

Related

Python subprocess.Popen terminates when stdin=PIPE is specified

I'm new to subprocesses in python, I need to spawn a number of independent subprocesses, keep them alive and pass commands into them. At first sight, subprocess library is what I'm looking for.
I've read the documenations for it and as I'm understanding to pass any command into the subprocess, I'd have to specify the input.
I need to run commands via windows command line, hence the toy example below is good enough that if I have it working, I'm pretty much done. Running code below via IDLE opens a new cmd window, printing a list of cwd files, however I can't write to it as stdin is not specified (would be writing to it using p.stdin.write('DIR') with 'DIR' being an example command).
from subprocess import Popen, PIPE
p = Popen(['cmd', '/K', 'DIR'])
Therefore I specify the stdin as PIPE, as per documentations.
from subprocess import Popen, PIPE
p = Popen(['cmd', '/K', 'DIR'], stdin=PIPE)
However, running the second snippet of code instantly terminates the opened cmd window. Is that the expected behavior? As far as I could find in the documentations, only p.kill() or p.terminate() end the child process. If so, what are the possible workarounds? If not, what am I doing incorrectly, what other libraries should I be using? Thanks!

Subprocess in Python 2.7 -- issuing commands into an engine

I'm new to Python, and I'm given an engine in bash (which takes its own unique commands from a command line prompt or a file and exercises a specific functionality). I want to subprocess it through Python.
I'm able to open the engine with subprocess.call(path, shell=True), and manually interact with it / input commands, but I cannot figure out how to script the unique commands to input into the engine through Python, to see the outputs automatically. I've tried to understand all of the documentation, but it is so, so verbose.
Ideally I would like to script all of my input commands in Python, subprocess the engine, and see the output from my engine in the Python output.
Again, forgive me if this sounds confusing. For example, I've tried:
p = subprocess.Popen(path-to-engine, stdin = subprocess.PIPE, stdout = subprocess.PIPE, shell=True)
p.stdin.write("some commands")
p.stdout.readline()
p.kill()
but this just gives me exit code 0, and no output.
You should use .communicate() instead of .kill():
import subprocess
p = subprocess.Popen(
path_to_engine,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
p.stdin.write("some commands\n")
stdout, stderr = p.communicate()
print('stdout:')
print(stdout)
print('stderr:')
print(stderr)

Is it possible to capture output from a system command and redirect it?

What I would like to do is:
run a ruby script...
that executes a shell command
and redirects it to a named pipe accessible outside the script
from the system shell, read from that pipe
That is, have the Ruby script capture some command output and redirect it in such a way that it's connectable to from outside the script?
I want to mention that the script cannot simply start and exit, since it's a REPL. The idea is that using the REPL you would be able to run a command and redirect its output elsewhere to consume it.
Using abort and an exit message, will pass the message to STDERR (and the script will fail with exit code 1). You can pass this shell command output in this way.
This is possibly not the only (or best) way, but it has worked for me in the past.
[edit]
You can also redirect the output to a file (using standard methods), and read that file outside the ruby script.
require 'open3'
stdin, stderr, status = Open3.capture3(commandline)
stdin.chomp #Here, you should ge
Incase, if someone wanted to use you can get the output via stdin.chomp

Ruby Command Prompt Commands

I am designing a ruby program that needs to run a command and store it a variable.
var = exec('some command');
This doesn't work the way I want it to, it just prints the output from the command prompt and then ends the program.
So is there a function that doesn't end the program, doesn't print the cmd output and stores the information in a variable?
Thanks in advance.
You need to use either Ruby's built in backtick syntax, or use %x
output = `some command`
or
output = %x(some "command")
Open3 grants you access to stdin, stdout, stderr and a thread to wait
the child process when running another program. You can specify
various attributes, redirections, current directory, etc., of the
program as Process.spawn.
See the various ways of executing a command

python Input delegation for subprocesses

I am currently displaying the output of a subprocess onthe python shell (in my case iDLE on windows) by using a pipe and displaying each line.
I want to do this with a subprocess that has user input, so that the prompt will appear on the python console, and the user can enter the result, and the result can be send to the subprocess.
Is there a way to do this?
Use process.stdin.write.
Remember to set stdin = subprocess.PIPE when you call subprocess.Popen.

Resources