I'm working on developing some tools in Python to be used in Linux via Bash or another CLI. These tools all print info to the terminal to let the user know what's going on. Some have progress percentages where the same line is printed to repeatedly.
I've got everything working how I'd like with print statements, however, occasionally these tools may be sent to the background in Bash. This is causing problems, since the print function seems to print to the foreground regardless of where the process is running.
How do I only print to the console when the script in the foreground. The script should keep running and just not print to the foreground when sent to the background. I imagine there's some whole topic I'm missing to do this, as I am new to programming as a whole. Even if I could get a pointer in the right direction, that would likely get me there.
CodePudding user response:
Enabling TOSTOP
in termios
should work for your case
#! /usr/bin/env python3
import sys
import termios
import tty
try:
[iflag, oflag, cflag, lflag, ispeed, ospeed, ccs] = termios.tcgetattr(sys.stdout)
termios.tcsetattr(sys.stdout.fileno(), termios.TCSANOW, [iflag, oflag, cflag, lflag | termios.TOSTOP, ispeed, ospeed, ccs])
except termios.error:
pass
...
# your script here
...
# restore the original state when done
so if your script tries to print to stdout
when in background it's going to receive a SIGTTOU
signal and stops.
This should work either if you start it with &
or you send it to background later using job control (CTRL Z).
edit
If you need it to continue running handle the SIGCONT
signal
signal.signal(signal.SIGCONT, handler)
and in handler
switch a flag
def handler(signum, frame):
global do_print
do_print = False
CodePudding user response:
I'm not sure this is the most ideal or elegant solution, but here's what I've gotten to work based upon this answer to a similar question:
#! /usr/bin/env python3
import time, sys, os
def termianl_output(data): #Function to print to console ONLY if process in foreground
if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()):
print(data)
count = 0
while count < 20:
count = 1
terminal_output(count)
time.sleep(2)
I've simply put together a new function to handle printing that first checks whether the process group it's running in is the process group that has control of the terminal. If it's not, it does not print. This could be easily modified to instead output to a log file or something, though I don't need that in my case.