3

How can I set the window title of a GNOME terminal from Python?

I am running several python scripts from different terminals. I would like that the python script, once executed, automatically set the window title to some status text that I can modify from within the script.

becko
  • 13,246
  • 24
  • 74
  • 144
  • Can you post the code you're using to launch the terminal? Do you want it to change or remain static for the whole session? – Jimmy Smith Sep 16 '14 at 15:15
  • Can't try this now, but I would choose [one way](http://askubuntu.com/questions/30988/how-do-you-set-the-title-of-the-active-gnome-terminal-from-the-command-line) of doing it without python, and then [call the external command](http://stackoverflow.com/questions/89228/calling-an-external-command-in-python?rq=1). – fredtantini Sep 16 '14 at 15:17

3 Answers3

7

You can use XTerm control sequence:

print(b'\33]0;title you want\a')

NOTE: Above statement will print additional newline. To avoid it, use sys.stdout.write:

import sys
sys.stdout.write(b'\33]0;title you want\a')
sys.stdout.flush()

In Python 3.x:

print('\33]0;title you want\a', end='')
sys.stdout.flush()

In Python 3.3+:

print('\33]0;title you want\a', end='', flush=True)

OR

sys.stdout.buffer.write(b'\33]0;title you want\a')
sys.stdout.buffer.flush()
wjandrea
  • 16,334
  • 5
  • 30
  • 53
falsetru
  • 314,667
  • 49
  • 610
  • 551
2

The accepted answer was wrong for Python3. This works on Python >= 3.6:

terminal_title = "title you want"
print(f'\33]0;{terminal_title}\a', end='', flush=True)

The flush is essential; See comments.

I also do not recommend checking if os.environ['TERM'] == 'xterm' like another answer does because some terminals fail that check even though they support the OSC escape code:

[navin@Radiant ~]$ echo $TERM
xterm-256color
[navin@Radiant ~]$ echo $TERM_PROGRAM
iTerm.app
Navin
  • 2,866
  • 2
  • 23
  • 46
  • 1
    I didn't notice I posted a non-working code for python 3.x until saw your answer. Thank you. – falsetru Nov 13 '17 at 17:26
  • 1
    @falsetru Besides the print(b'') you fixed, this is surprisingly tricky: `stdout.flush()` is absolutely necessary for sys.stdout and `flush=True` is necessary for print(). Without it, my code stopped working as soon as I removed my debugging print() statements which auto-flushed stdout on every `\n`. Your answer breaks randomly for the same reason if you try to set a small title that doesn't trigger python/libc's auto-flush. – Navin Nov 15 '17 at 12:43
  • Thanks for the feedback, though I would have appreciated a comment on my answer to notify me. I've fixed it now - added the terminals that I know support the OSC code, though I'm not sure they all support setting the title. – wjandrea Feb 10 '18 at 00:48
  • Regarding flushing the buffer, I'm not sure what you mean. I've even tried setting the title to a null string and it works fine. Maybe other systems don't handle it as well? For reference, I'm using Python 2.7.6 and 3.4.3 in Gnome Terminal on Ubuntu. Also could you add that info into your answer? – wjandrea Feb 10 '18 at 00:51
  • @WJAndrea Regarding flushing: Perhaps you're running in interactive mode? The documentation is clear, your code is broken if it doesn't flush the buffer: `When interactive, standard streams are line-buffered. Otherwise, they are block-buffered like regular text files.` – Navin Feb 10 '18 at 01:27
  • @Navin Yes, interactive mode. Thanks, I'll fix that now. – wjandrea Feb 10 '18 at 01:28
  • @WJAndrea Regarding `$TERM`: I still think that checking it is a bad idea. The only thing you should check is whether stdout is connected to a tty. Otherwise, you're playing whack-a-mole with all the crap that different terminals name themselves. cf. https://webaim.org/blog/user-agent-string-history/ – Navin Feb 10 '18 at 01:31
  • @Navin That's valid, but I'm not really going for compatibility. It covers the most common terminals right now, and adapting it for other ones just involves adding to the tuple, or removing the check entirely, like you said. – wjandrea Feb 10 '18 at 01:58
1

Adding to falsetru's answer, Python (2 and 3) also supports writing regular strings to stdout:

import sys
sys.stdout.write('\33]0;title you want\a')
sys.stdout.flush()

By the way, I put this in my ~/.pythonstartup file to set the title when opening a Python shell:

import os
import sys

def set_xterm_title(title='Python %d.%d.%d' % sys.version_info[:3]):
    '''
    Set XTerm title using escape sequences.
    By default, sets as 'Python' and the version number.
    '''
    sys.stdout.write('\33]0;' + title + '\a')
    sys.stdout.flush()

# Make sure this terminal supports the OSC code (\33]),
# though not necessarily that it supports setting the title.
# If this check causes compatibility issues, you can add
# items to the tuple, or remove the check entirely.
if os.environ.get('TERM') in (
        'xterm',
        'xterm-color',
        'xterm-256color',
        'linux',
        'screen',
        'screen-256color',
        'screen-bce',
        ):
    set_xterm_title()
wjandrea
  • 16,334
  • 5
  • 30
  • 53