Invoking C compiler using Python subprocess command

c, python, shell

Solution

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.call` with `shell = True` always creates non-interactive non-login instances of `/bin/sh` - note that it is NOT the user's default shell that is used.

`sh` does NOT read initialization files for non-interactive non-login shells (neither system-wide nor user-specific ones).

- Note that even on platforms where `sh` is `bash` in disguise, `bash` will act this way when invoked as `sh`.

Every shell instance created with `subprocess.call` with `shell = True` is 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 `env` parameter; note, however, that you'll have to supply the entire environment in that event, potentially including variables such as `USER` and `HOME`, if needed; simple example, defining `$PATH` explicitly:

subprocess.call('echo $PATH', shell = True, \
                env = { 'PATH': '/sbin:/bin:/usr/bin' })

Problem

I am trying to compile a C program using Python and want to give input using "<" operator but it's not working as expected. If I compile the C program and run it by giving input though a file it works; for example ``` ./a.out <inp.txt works ``` But similarly if I try to do this using a Python script, it did not quite work out as expected. For example: ``` import subprocess subprocess.call(["gcc","a.c","-o","x"]) subprocess.call(["./x"]) ``` and ``` import subprocess subprocess.call(["gcc","a.c","-o","x"]) subprocess.call(["./x","<inp.txt"]) ``` Both script ask for input though terminal. But I think in the second script it should read from file. why both the programs are working the same?

Original source