Skip to content

Curses terminal resize problems when Python is in interactive mode #46927

Closed

Description

@pbazant
mannequin
BPO 2675
Nosy @bitdancer, @vadmium

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2008-04-23.15:41:39.440>
labels = ['extension-modules', 'type-bug', 'docs']
title = 'Curses terminal resize problems when Python is in interactive mode'
updated_at = <Date 2016-05-15.01:05:47.735>
user = 'https://bugs.python.org/pbazant'

bugs.python.org fields:

activity = <Date 2016-05-15.01:05:47.735>
actor = 'martin.panter'
assignee = 'docs@python'
closed = False
closed_date = None
closer = None
components = ['Documentation', 'Extension Modules']
creation = <Date 2008-04-23.15:41:39.440>
creator = 'pbazant'
dependencies = []
files = []
hgrepos = []
issue_num = 2675
keywords = []
message_count = 6.0
messages = ['65700', '109298', '109325', '161020', '161021', '265564']
nosy_count = 5.0
nosy_names = ['pbazant', 'r.david.murray', 'docs@python', 'poq', 'martin.panter']
pr_nums = []
priority = 'normal'
resolution = None
stage = 'needs patch'
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue2675'
versions = ['Python 2.7', 'Python 3.5', 'Python 3.6']

Linked PRs

Activity

  1. pbazant commented on Apr 23, 2008

    pbazantmannequin
    MannequinAuthor

    When python is in interactive mode, curses does not react to resize
    events properly.

    test.py:

    import curses
    
    def run():
     stdscr=curses.initscr()
     key=0
     while(key!=ord('q')):
      key=stdscr.getch()
      stdscr.addstr(0,0,str(stdscr.getmaxyx())+' '+str(key))
      stdscr.refresh()
     curses.endwin()
    
    run()

    When this is run directly, everything is ok. When it is called via
    execfile() from the interactive prompt, it shows the right screen size
    after the first keypress, but behaves oddly after the resize.

    IMHO, the following happens:
    For some reason, env. variables LINES and COLUMNS are set but they are
    not reflected in the os.environ structure nor they respond to screen
    size changes. If these variables are set then the ncurses library (see
    man pages) uses their values instead of getting the term size via
    ioctl.
    The ncurses library receives a SIGWINCH and sees that LINES
    and COLUMNS are set. However, their values are same as the
    screen dimensions before the resize, so it is perplexed why there is
    a SIGWINCH if the screen did not change and it just ungetchs an ERR
    and ncurses internal structures are not changed appropriately.

    From the resizeterm man page:
    "If the environment variables LINES or COLUMNS are set, this overrides
    the library's use of the window size obtained from the operating
    system. Thus, even if a SIGWINCH is received, no screen size change may
    be recorded. In that case, no KEY_RESIZE is queued for the next call to
    getch; an ERR will be returned instead."

    Executing

    import os
    os.environ['LINES']="blah"
    del os.environ['LINES']
    os.environ['COLUMNS']="blah"
    del os.environ['COLUMNS']

    solves the problem for me.
    Perhaps the problem has sth to do with python using readline
    in interactive mode???
    PB

  2. BreamoreBoy commented on Jul 5, 2010

    BreamoreBoymannequin
    Mannequin

    Could somebody witht a nix box try this out, I'd do it myself if I had such a beast.

  3. bitdancer commented on Jul 5, 2010

    @bitdancer
    Member

    Well, I can run it, but I have no idea what it is telling me or how it demonstrates a bug. Pavel, is this still a problem in 2.6/2.7?

  4. poq commented on May 17, 2012

    poqmannequin
    Mannequin

    Just to confirm: curses SIGWINCH handling is still (2.7/3.2) broken after importing readline.

    Readline seems to set the LINES/COLUMNS environment vars, and this confuses curses, even if curses is imported after readline.

    Clearing the LINES/COLUMNS vars after import readline fixes the issue:
    os.environ['LINES'] = os.environ['COLUMNS'] = ''
    or
    os.unsetenv('LINES'); os.unsetenv('COLUMNS')
    (or other variations).

    I spent a couple hours tearing my hair out over this, before I found this report.

    It may be possible for Python to work around this readline behavior by saving LINES/COLUMNS and restoring them after initializing readline.

    Or maybe this should just be documented somewhere.

  5. poq commented on May 17, 2012

    poqmannequin
    Mannequin

    bpo-3948 is almost certainly a duplicate.

  6. vadmium commented on May 15, 2016

    @vadmium
    Member

    For the record, this is my interpretation of Pavel’s demo:

    If you press a key (other than lowercase “q”) or resize the terminal, it displays the terminal dimensions in the top-left corner. Without Readline, the dimensions are updated when the terminal resizes.

    When Readline is used (interactive mode, or simply “import readline”), the reported dimensions are static, which I understand is the bug.

    Documentating this quirk may be a good start.

  7. transferred this issue fromon Apr 10, 2022
  8. mbriand commented on May 4, 2025

    @mbriand
    Contributor

    I've been tracking a similar issue for a few days now: importing readline module is adding LINES and COLUMNS variables to the environment. Values are set to the terminal size at time of module import and never updated.

    Reproduce

    So with this reproduce code:

    #!/usr/bin/env python3
    
    import readline
    import subprocess
    import time
    import pprint
    
    time.sleep(3)
    pprint.pprint(subprocess.check_output(["env"]).decode())
    

    If I run it, we can see the both environment variables are set:

    ./test.py | grep "'LINES=\|COLUMNS="
     'LINES=64\n'
     'COLUMNS=225\n')
    

    The problem is, if we do resize the terminal or change font size during the sleep() call, LINES and COLUMNS values are not updated correctly.

    You can confirm this is indeed linked to the readline module import, if I remove it, these two variables are not set.

    Analysis

    I've been tracking where these variables are set, and this actually comes from the readline C library. This behaviour can be changed from the cpython source code using rl_change_environment: https://git.savannah.gnu.org/cgit/readline.git/tree/doc/readline.info#n3201

    I made the following modification in cpython, and the variables are not set anymore.

    diff --git i/Modules/readline.c w/Modules/readline.c
    index 35655c70a461..1bd558830900 100644
    --- i/Modules/readline.c
    +++ w/Modules/readline.c
    @@ -1247,6 +1247,7 @@ flex_complete(const char *text, int start, int end)
     static int
     setup_readline(readlinestate *mod_state)
     {
    +       rl_change_environment = 0;
     #ifdef SAVE_LOCALE
         char *saved_locale = strdup(setlocale(LC_CTYPE, NULL));
         if (!saved_locale) {
    

    Fix ?

    Now I would be happy to open a PR with this change, but I have some doubts: I'm not sure there would not be any unexpected side effect with this.

  9. added 3 commits that reference this issue on May 7, 2025
  10. added 2 commits that reference this issue on Jul 3, 2026
  11. added a commit that references this issue on Jul 8, 2026
  12. mbriand commented on Jul 10, 2026

    @mbriand
    Contributor

    I tested again the original reproducer script, on today main branch. I do confirm it now shows correct values, both while executed stand-alone of from an interactive session (using exec(open("/home/mathieu/tmp/test.py").read())).

    So I believe we can close this PR, as fixed by the above PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.16new features, bugs and security fixesdocsDocumentation in the Doc dirextension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions