best way to go about with a script that seems to need both bash and python functionality
Gonna try and put this into words.
I am pretty familiar with bash and python. used both quite a bit and feel more or less comfortable with them.
My issue is I often do a thing where if I want to accomplish a task that is maybe a bit complex, I feel like I have to wind up making a script, let's call it hello_word.sh
but then I also make a script called .hello_world.py
and basically what I do is almost the first line of the bash script, I call the python script like ./hello_world.py $@
and take advtange of the argparse
library in python to determine what the user wants to do amongst other tasks that are easier to do in python like for loops and etc.
I try to do the meat of the logic in the python scripts before I write to an .env
file from it and then in the bash script, I will do
set -o allexport
source "${DIR}"/"${ENV_FILE}"
set +o allexport
and then use the variable from that env file to do the rest of the logic in bash.
why do I do anything in bash?
cause I very much prefer being able to see a terminal command being executed in real-time and see what it does and be able to Ctrl+c
if I see the command go awry.
in python, you can run a command with subprocess
or other similar system libraries but you can't get the output in real-time or terminate a command preemptively and I really hate that. you have to wait for the command to end to see what happened.
But I feel like there is something obvious I am missing (like maybe bash has an argparse library I don't know about and there is some way to inject the concept of types into it) or if there is another language entirely that fits my needs?
I'm not sure what bash is getting you here. If all you want is to be able to run a subprocess and pipe it's output to stdout in realtime, all you need to do is poll the output in a loop.
already answered this
Why would polling the subprocess not do the trick? A kill command to the python script will also kill its children.
does polling a subprocess allow you to interact with that subprocess? like if it asks for input and that kind of thing?
Python gives you total control of all the input and output streams of all the subprocesses. It's a bit more verbose than Bash but I promise it's not missing any features.
A demo of some PIPE gymnastics in case it's helpful: Two subprocesses interacting with each other and Python code to glue them together.
The first subprocess is a bash script that echoes lines from stdin with
-I
prepended. Python forwards stdin directly to this subprocess, but it intercepts stdout.Each of those outputs is passed as an argument to a new
date
process. The-I<format>
prints the ISO timestamp to given precisiondate
,hours
, etc. Python again intercepts the output.If the date process succeeded, it URL-escapes the formatted date and prints it. If it failed (due to invalid argument), it prints the error message unchanged.
Keyboard interrupt Ctrl+C works at any point. You can also send end-of-file Ctrl+D to end everything gracefully.
Probably not the best way to solve this problem, but a demonstration of data weaving between processes without delays.
Some sample output:
Now obviously in practice this particular problem could be solved in a million easier ways - but I hope this convinces you that Python is not missing any features regarding piping data and handling interrupts. I haven't even touched
import io
oros.mkfifo
which together generalize shell scripting concepts like process substitution andtee
and similar.If Ctrl+C doesn't work for some reason, then some component somewhere is improperly intercepting those interrupts. It's probably not a Python (or bash) issue.
That's up to what the python parent wants to do. You can detect particular prompts from stdout, and pass through user input when it happens on a case-by-case basis.
For a more generic approach, you'll have to use either threading or asyncio. With async, for instance, you can just wait on stdin and stdout on the subprocess in a loop.
You absolutely can Ctrl + C out of a running python script in the same way you can a bash script. The other reason you want to be using bash here, to "see the output of the program", confuses me a little -- do you just want it to log information to console while it's running? or is there some other bash-unique information you can get on a running script that you're really looking for here?
I'm not that familiar with bash or python, but my world is dotnet, and you can absolutely do what functionality you describe with just C#/F#, and i'm positive its the same for python.
This does sound like one of those awkward problems where its all about wording the question properly though. To me it sounds like you just want the program to log to the console while its running while also retaining the ability to kill the process mid run correct?
Indeed, I had a hell of a time figuring out how to convert my needs to words for this post.
And also to be able to interact with the bash command if it asks for input, yes.
Ok it's been forever since i've touched python, so i'm cheating a bit, but as an example of pseduocode, would this roughly look like the kind of execution you're expecitnng?
I can't mock it up right this second and run it, but this seems to:
So maybe i'm misunderstanding the "interact with the bash command" part, but even then I feel like you could just do the command in python and have it pull input?
https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/
Does this help out at all?