Home > Blockchain >  Stop printing to BASH console when Python script is moved to background
Stop printing to BASH console when Python script is moved to background

Time:03-10

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.

  • Related