To run a set of Python commands from a bash
script, you must give the Python interpreter the commands to run, either from a file (Python script) that you create in the script, as in
#!/bin/bash -e
# Create script as "script.py"
cat >script.py <<'END_SCRIPT'
print("TESTPRINT")
END_SCRIPT
# Run script.py
python script.py
rm script.py
(this creates a new file called script.py
or overwrites that file if it already exists, and then instructs Python to run it; it is then deleted)
... or directly via some form of redirection, for example a here-document:
#!/bin/bash
python - <<'END_SCRIPT'
print("TESTPRINT")
END_SCRIPT
What this does is running python -
which instructs the Python interpreter to read the script from standard input. The shell then sends the text of the Python script (delimited by END_SCRIPT
in the shell script) to the Python process' standard input stream.
Note that the two bits of code above are subtly different in that the second script's Python process has its standard input connected to the script that it's reading, while the first script's Python process is free to read data other than the script from standard input. This matters if your Python code reads from standard input.
Python can also take a set of commands from the command line directly with its -c
option:
#!/bin/bash
python -c 'print("TESTPRINT")'
What you can't do is to "switch to Python" in the middle of a bash
script.
The commands in a script is executed by bash
one after the other, and while a command is executing, the script itself waits for it to terminate (if it's not a background job).
This means that your original script would start Python in interactive mode, temporarily suspending the execution of the bash
script until the Python process terminates. The script would then try to execute print("TESTPRINT")
as a shell command.
It's a similar issue with using ssh
like this in a script:
ssh user@server
cd /tmp
ls
(which may possibly be similar to what you say you tried a few years ago).
This would not connect to the remote system and run the cd
and ls
commands there. It would start an interactive shell on the remote system, and once that shell has terminated (giving control back to the script), cd
and ls
would be run locally.
Instead, to execute the commands on a remote machine, use
ssh user@server "cd /tmp; ls"
(This is a lame example, but you may get the point).
The below example shows how you may actually do what you propose. It comes with several warning label and caveats though, and you should never ever write code like this (because it's obfuscated and therefore unmaintainable and, dare I say it, downright bad).
python -
print("TESTPRINT")
Running it:
$ sh -s <script.sh
TESTPRINT
What happens here is that the script is being run by sh -s
. The -s
option to sh
(and to bash
) tells the shell to execute the shell script arriving over the standard input stream.
The script then starts python -
, which tells Python to run whatever comes in over the standard input stream. The next thing on that stream, since it's inherited from sh -s
by Python (and therefore connected to our script text file), is the Python command print("TESTPRINT")
.
The Python interpreter would then continue reading and executing commands from the script file until it runs out or executes the Python command exit()
.