You have to open the subprocess like this:
import subprocess
cmd = subprocess.Popen(['./myprogram'], stdin=subprocess.PIPE)
This means that cmd will have a .stdin you can write to; print by default sends output to your Python script's stdout, which has no connection with the subprocess' stdin. So do that:
cmd.stdin.write('1\n') # tell myprogram to select 1
and then quite probably you should:
cmd.stdin.flush() # don't let your input stay in in-memory-buffers
or
cmd.stdin.close() # if you're done with writing to the subprocess.
PS If your Python script is a long-running process on a *nix system and you notice your subprocess has ended but is still displayed as a Z (zombie) process, please check that answer.
Answer from tzot on Stack OverflowYou have to open the subprocess like this:
import subprocess
cmd = subprocess.Popen(['./myprogram'], stdin=subprocess.PIPE)
This means that cmd will have a .stdin you can write to; print by default sends output to your Python script's stdout, which has no connection with the subprocess' stdin. So do that:
cmd.stdin.write('1\n') # tell myprogram to select 1
and then quite probably you should:
cmd.stdin.flush() # don't let your input stay in in-memory-buffers
or
cmd.stdin.close() # if you're done with writing to the subprocess.
PS If your Python script is a long-running process on a *nix system and you notice your subprocess has ended but is still displayed as a Z (zombie) process, please check that answer.
Maybe flush stdout?
print("", flush=True,end="")
Running a C executable inside a python program - Stack Overflow
subprocess, invoke C-program from within Python - Stack Overflow
How do I create a python file that interacts with c executable, and saves its output to variables?
python - C program and subprocess - Stack Overflow
subprocess.run has optional stdout argument, you might give it file handle, so in your case something like
import subprocess
import sys
filestem = sys.argv[1]
with open('outputfile','wb') as f:
subprocess.run(['/home/dev/executable_file', filestem],stdout=f)
should work. I do not have ability to test it so please run it and write if it does work as intended
You have several options:
NOTE - Tested in CentOS 7, using Python 2.7
1. Try pexpect:
"""Usage: executable_file argument ("ex. stack.py -lh")"""
import pexpect
filestem = sys.argv[1]
# Using ls -lh >> outputfile as an example
cmd = "ls {0} >> outputfile".format(filestem)
command_output, exitstatus = pexpect.run("/usr/bin/bash -c '{0}'".format(cmd), withexitstatus=True)
if exitstatus == 0:
print(command_output)
else:
print("Houston, we've had a problem.")
2. Run subprocess with shell=true (Not recommended):
"""Usage: executable_file argument ("ex. stack.py -lh")"""
import sys
import subprocess
filestem = sys.argv[1]
# Using ls -lh >> outputfile as an example
cmd = "ls {0} >> outputfile".format(filestem)
result = subprocess.check_output(shlex.split(cmd), shell=True) # or subprocess.call(cmd, shell=True)
print(result)
It works, but python.org frowns upon this, due to the chance of a shell injection: see "Security Considerations" in the subprocess documentation.
3. If you must use subprocess, run each command separately and take the SDTOUT of the previous command and pipe it into the STDIN of the next command:
p = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE)
stdout_data, stderr_data = p.communicate()
p = subprocess.Popen(cmd, stdin=stdout_data, stdout=PIPE)
etc...
Good luck with your code!
Hi, I have this simple c program:
#include <stdio.h>
void secretFunction() { printf("Congratulations!\n"); printf("You have entered in the secret function!\n"); }
void echo() { char buffer[20];
printf("Enter some text:\n"); scanf("%s", buffer); printf("You entered: %s\n", buffer);}
int main() { echo();
return 0; }It includes a buffer overflow, but that's not really the important part right now. This is what the output looks like:
Enter some text: enteringmyname You entered: enteringmyname
What I am trying to do, is create a python file that is able to run this file, save the lines that it gives to some variables, and then give it some input depending on that output.
Currently this is what I have:
import subprocess
p = subprocess.Popen("./vuln_nostack", shell=False)p.communicate()
This runs the file like I want, and then just runs the file in the python terminal.
This is not reaaally what I want though.
I want to be able to save the lines that it outputs to variables in my python program, and then output something.
I then tried all kinds of things to make a program that could interact a little more with the executable.
I made a python script that imitates, and does the same thing as the c program:
inp = input("Enter some text:\n")
print("you entered: " + inp)And then I made this python program to interact with it:
import subprocess
command = "python3 dummy.py"
p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
v = p.stdout.readline() print(v) output, err = p.communicate(input="{}\n".format(v))
print(output)and this does exactly what I want, I can save the ouput, and input something based on it.
But when I run this exact same program, but instead point it to the c executable, the program just hangs, and nothing happens.
Why does this happen? and can I get my python file to talk to the executable in the way that I want?
I really can't find something that explain this behaviour; can someone help me understanding?
There are at least two issues here:
the C program's standard output is to a non-interactive device (a pipe) and therefore the output is fully buffered. The output will be accumulated in memory, only being sent to the output device when (i) the buffer fills, or (ii) it is manually flushed, or (iii) the program terminates normally.
the C program runs indefinitely, with no way to make it terminate normally. Not even end-of-file on its standard input will make it stop.
On the Python side, then, the script is waiting for the subprocess's output to be flushed, whereas the subprocess needs to read and echo more data (probably a lot of it) before that will happen. This is a deadlock.
Your best approach depends on how well the example C program models the behavior of the one in which you're really interested.
If it's faithful in every relevant detail, then the only thing you can reasonably do is keep writing to the subprocess's
stdinuntil something pops out on itsstdout. You probably want to do the data pushing in a separate thread, to avoid reproducing exactly the same kind of deadlock you already saw.If it recognizes some kind of clean termination signal, such as a "quit" command or EOF on its standard input, then have the Python side send that signal before trying to read the output. Indeed, you already close
stdin, so perhaps you don't actually need to do anything to accommodate the real program.
Note well that the first alternative leaves the subprocess running. You will want to ensure that it terminates. By terminate()ing or kill()ing it, if that's what it takes.
Change these:
Send a separator between the numbers read by the C program. scanf(3) accepts any non-digit byte as separator. For easiest buffering, send a newline (e.g.
.write(b'42\n')) from Python. Without a separator, scanf(3) will wait for more digits indefinitely.After each write (both in C and Python), flush the output.
This works for me:
#include <stdio.h>
int main(int argc, char *argv[])
{
int n;
while (1){
scanf("%d", &n);
printf("%d\n", n);
fflush(stdout); /* I've added this line only. */
}
return 0;
}
import subprocess
p = subprocess.Popen(
('./a.out',), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
try:
print('A'); p.stdin.write(b'42 '); p.stdin.flush()
print('B'); print(repr(p.stdout.readline()));
print('C'); p.stdin.write(b'43\n'); p.stdin.flush()
print('D'); print(repr(p.stdout.readline()));
finally:
print('E'); print(p.kill())
The reason why your original C program works when run interactively within the terminal window is that in C the output is automatically flushed when a newline (\n) is written to the terminal. Thus printf("%d\n", n); does an implicit fflush(stdout); in the end.
The reason why your original C program doesn't work when run from Python with subprocess is that it writes its output to a pipe (rather than to a terminal), and there is no autoflush to a pipe. What happens is that the Python program is waiting for bytes, and the C program doesn't write those bytes to the pipe, but it is waiting for more bytes (in the next scanf), so both programs are waiting for the other indefinitely. (However, there would be a partial autoflush after a few KiB (typically 8192 bytes) of output. But a single decimal number is too short to trigger that.)
If it's not possible to change the C program, then you should use a terminal device instead of a pipe for communication between the C and the Python program. The pty Python module can create the terminal device, this works for me with your original C program:
import os, pty, subprocess
master_fd, slave_fd = pty.openpty()
p = subprocess.Popen(
('./a.out',), stdin=slave_fd, stdout=slave_fd,
preexec_fn=lambda: os.close(master_fd))
try:
os.close(slave_fd)
master = os.fdopen(master_fd, 'rb+', buffering=0)
print('A'); master.write(b'42\n'); master.flush()
print('B'); print(repr(master.readline()));
print('C'); master.write(b'43\n'); master.flush()
print('D'); print(repr(master.readline()));
finally:
print('E'); print(p.kill())
If you don't want to send newlines from Python, here is a solution without them, it works for me:
import os, pty, subprocess, termios
master_fd, slave_fd = pty.openpty()
ts = termios.tcgetattr(master_fd)
ts[3] &= ~(termios.ICANON | termios.ECHO)
termios.tcsetattr(master_fd, termios.TCSANOW, ts)
p = subprocess.Popen(
('./a.out',), stdin=slave_fd, stdout=slave_fd,
preexec_fn=lambda: os.close(master_fd))
try:
os.close(slave_fd)
master = os.fdopen(master_fd, 'rb+', buffering=0)
print('A'); master.write(b'42 '); master.flush()
print('B'); print(repr(master.readline()));
print('C'); master.write(b'43\t'); master.flush()
print('D'); print(repr(master.readline()));
finally:
print('E'); print(p.kill())
To complement @Jonathan Leffler's and @alastair's helpful answers:
Assuming you control the string you're passing to the shell for execution, I see nothing wrong with using the shell for convenience. [1]
subprocess.call() has an optional Boolean shell parameter, which causes the command to be passed to the shell, enabling I/O redirection, referencing environment variables, ...:
subprocess.call("./x <inp.txt", shell = True)
Note how the entire command line is passed as a single string rather than an array of arguments.
[1] Avoid use of the shell in the following cases:
- If your Python code must run on platforms other than Unix-like ones, such as Windows.
- If performance is paramount.
- If you find yourself "outsourcing" tasks better handled on the Python side.
If you're concerned about lack of predictability of the shell environment (as @alastair is):
subprocess.callwithshell = Truealways creates non-interactive non-login instances of/bin/sh- note that it is NOT the user's default shell that is used.shdoes NOT read initialization files for non-interactive non-login shells (neither system-wide nor user-specific ones).- Note that even on platforms where
shisbashin disguise,bashwill act this way when invoked assh.
- Note that even on platforms where
Every shell instance created with
subprocess.callwithshell = Trueis its own world, and its environment is neither influenced by previous shell instances nor does it influence later ones.However, the shell instances created do inherit the environment of the python process itself:
If you started your Python program from an interactive shell, then that shell's environment is inherited. Note that this only pertains to the current working directory and environment variables, and NOT to aliases, shell functions, and shell variables.
Generally, that's a feature, given that Python (CPython) itself is designed to be controllable via environment variables (for 2.x, see https://docs.python.org/2/using/cmdline.html#environment-variables; for 3.x, see https://docs.python.org/3/using/cmdline.html#environment-variables).
If needed, you can supply your own environment to the shell via the
envparameter; note, however, that you'll have to supply the entire environment in that event, potentially including variables such asUSERandHOME, if needed; simple example, defining$PATHexplicitly:subprocess.call('echo $PATH', shell = True, \ env = { 'PATH': '/sbin:/bin:/usr/bin' })
The shell does I/O redirection for a process. Based on what you're saying, the subprocess module does not do I/O redirection like that. To demonstrate, run:
subprocess.call(["sh","-c", "./x <inp.txt"])
That runs the shell and should redirect the I/O. With your code, your program ./x is being given an argument <inp.txt which it is ignoring.
NB: the alternative call to subprocess.call is purely for diagnostic purposes, not a recommended solution. The recommended solution involves reading the (Python 2) subprocess module documentation (or the Python 3 documentation for it) to find out how to do the redirection using the module.
import subprocess
i_file = open("inp.txt")
subprocess.call("./x", stdin=i_file)
i_file.close()
If your script is about to exit so you don't have to worry about wasted file descriptors, you can compress that to:
import subprocess
subprocess.call("./x", stdin=open("inp.txt"))
Your syntax is mostly correct.
The error message is quite clear: subprocess.call(), which use subprocess.Popen class as backend, does not accept a keyword argument 'check'
Remove that argument and try again.
If you want CalledProcessError to be raised when the called process return non-zero returncodes, use subprocess.check_call() instead.
Well, I have kept the whole argument in a single quote, then it worked, removing, check and capture_output:
subprocess.call(["./pngCamCalStep1 home/nvi/Perception/sensor_0/left-%04d.png 12 8 0.05"], cwd='/home/nvi/camera_intrinsic_calibration/',shell =True)
There is no such thing as a C script. If you meant a C program you need to compile spa.c and spa.h into an executable before running it.
If you use GCC in Linux or Mac OS X:
$ gcc -Wall spa.c -o spa
Will get you an executable named spa.
After that, you can run spa program from your Python script with:
from subprocess import call
call(["./spa", "args", "to", "spa"])
cinpy comes close using the awesome combination of tcc and ctypes
The following code is ripped from cinpy_test.py included in the package.
import ctypes
import cinpy
# Fibonacci in Python
def fibpy(x):
if x<=1: return 1
return fibpy(x-1)+fibpy(x-2)
# Fibonacci in C
fibc=cinpy.defc("fib",
ctypes.CFUNCTYPE(ctypes.c_long,ctypes.c_int),
"""
long fib(int x) {
if (x<=1) return 1;
return fib(x-1)+fib(x-2);
}
""")
# ...and then just use them...
# (there _is_ a difference in the performance)
print fibpy(30)
print fibc(30)
Currently recommended way of running and controlling executables using Python is subprocess module. You can use different arguments, capture stdout, process it, or just redirect to arbitrary file. Have a look at documentation here https://docs.python.org/3.2/library/subprocess.html#module-subprocess
I'm not sure if this is what you're looking for, but you can use python to execute commands through the terminal. For example
import os
os.system("echo 'hello world'")
This will execute the terminal command >> echo 'hello world'