python -c vs python -<< heredoc

If you are using bash, you can avoid heredoc problems if you apply a little bit more of boilerplate:

python <(cat <<EoF

name = input()
print(f'hello, {name}!')

EoF
)

This will let you run your embedded Python script without you giving up the standard input. The overhead is mostly the same of using cmda | cmdb. This technique is known as Process Substitution.

If want to be able to somehow validate the script, I suggest that you dump it to a temporary file:

#!/bin/bash

temp_file=$(mktemp my_generated_python_script.XXXXXX.py)

cat > $temp_file <<EoF
# embedded python script
EoF

python3 $temp_file && rm $temp_file

This will keep the script if it fails to run.


The main flaw of using a here document is that the script's standard input will be the here document. So if you have a script which wants to process its standard input, python -c is pretty much your only option.

On the other hand, using python -c '...' ties up the single-quote for the shell's needs, so you can only use double-quoted strings in your Python script; using double-quotes instead to protect the script from the shell introduces additional problems (strings in double-quotes undergo various substitutions, whereas single-quoted strings are literal in the shell).

As an aside, notice that you probably want to single-quote the here-doc delimiter, too, otherwise the Python script is subject to similar substitutions.

python - <<'____HERE'
print("""Look, we can have double quotes!""")
print('And single quotes! And `back ticks`!')
print("$(and what looks to the shell like process substitutions and $variables!)")
____HERE

As an alternative, escaping the delimiter works identically, if you prefer that (python - <<\____HERE)


If you prefer to use python -c '...' without having to escape with the double-quotes you can first load the code in a bash variable using here-documents:

read -r -d '' CMD << '--END'
print ("'quoted'")
--END
python -c "$CMD"

The python code is loaded verbatim into the CMD variable and there's no need to escape double quotes.