Python

Как получить ширину окна консоли Linux в Python

Есть ли способ в Python программно определить ширину консоли? Я имею в виду количество символов, которые умещаются в одной строке без переноса, а не ширину окна в пикселях. Я ищу решение, работающее в Linux.

 

Ответ 1

import os

rows, columns = os.popen('stty size', 'r').read().split()

 Данный код использует команду 'stty size', которая, согласно теме в списке рассылки python, является достаточно универсальной в linux. Она открывает команду 'stty size' как файл, «читает» из него и использует простое разбиение строки для разделения координат.

В отличие от значения os.environ["COLUMNS"] (к которому я не могу получить доступ, несмотря на использование bash в качестве стандартной оболочки), данные будут актуальными, тогда как значение os.environ["COLUMNS"], как мне кажется, будет актуально только на момент запуска интерпретатора python.

 

Ответ 2

Пример:

import console

(width, height) = console.getTerminalSize()

print "Ширина терминала: %d" % width

Модуль, похоже, работает так: он проверяет, доступен ли termcap; если да — он использует его; если нет — он проверяет, поддерживает ли терминал специальный вызов ioctl; и если это тоже не работает, он проверяет переменные окружения, которые некоторые оболочки экспортируют для этого. Вероятно, это будет работать только на UNIX.

def getTerminalSize():

    import os

    env = os.environ

    def ioctl_GWINSZ(fd):

        try:

            import fcntl, termios, struct, os

            cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,

        '1234'))

        except:

            return

        return cr

    cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)

    if not cr:

        try:

            fd = os.open(os.ctermid(), os.O_RDONLY)

            cr = ioctl_GWINSZ(fd)

            os.close(fd)

        except:

            pass

    if not cr:

        cr = (env.get('LINES', 25), env.get('COLUMNS', 80))

 

        ### Используйте get(key[, default]) вместо try/catch

        #try:

        #    cr = (env['LINES'], env['COLUMNS'])

        #except:

        #    cr = (25, 80)

    return int(cr[1]), int(cr[0])



Ответ 3

Вот версия, которая работает как на linux, так и на os x и windows/cygwin:

""" getTerminalSize()

 - get width and height of console

 - works on linux,os x,windows,cygwin(windows)

"""

 

__all__=['getTerminalSize']

 

 

def getTerminalSize():

   import platform

   current_os = platform.system()

   tuple_xy=None

   if current_os == 'Windows':

       tuple_xy = _getTerminalSize_windows()

       if tuple_xy is None:

          tuple_xy = _getTerminalSize_tput()

          # необходим для работы с window's python в cygwin's xterm!

   if current_os == 'Linux' or current_os == 'Darwin' or  current_os.startswith('CYGWIN'):

       tuple_xy = _getTerminalSize_linux()

   if tuple_xy is None:

       print "default"

       tuple_xy = (80, 25)      # default value

   return tuple_xy

 

def _getTerminalSize_windows():

    res=None

    try:

        from ctypes import windll, create_string_buffer

 

        # stdin handle is -10

        # stdout handle is -11

        # stderr handle is -12

 

        h = windll.kernel32.GetStdHandle(-12)

        csbi = create_string_buffer(22)

        res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)

    except:

        return None

    if res:

        import struct

        (bufx, bufy, curx, cury, wattr,

         left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)

        sizex = right - left + 1

        sizey = bottom - top + 1

        return sizex, sizey

    else:

        return None

 

def _getTerminalSize_tput():

    # получить ширину терминала

    try:

       import subprocess

       proc=subprocess.Popen(["tput", "cols"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)

       output=proc.communicate(input=None)

       cols=int(output[0])

       proc=subprocess.Popen(["tput", "lines"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)

       output=proc.communicate(input=None)

       rows=int(output[0])

       return (cols,rows)

    except:

       return None

 

 

def _getTerminalSize_linux():

    def ioctl_GWINSZ(fd):

        try:

            import fcntl, termios, struct, os

            cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234'))

        except:

            return None

        return cr

    cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)

    if not cr:

        try:

            fd = os.open(os.ctermid(), os.O_RDONLY)

            cr = ioctl_GWINSZ(fd)

            os.close(fd)

        except:

            pass

    if not cr:

        try:

            cr = (env['LINES'], env['COLUMNS'])

        except:

            return None

    return int(cr[1]), int(cr[0])

 

if __name__ == "__main__":

    sizex,sizey=getTerminalSize()

    print  'width =',sizex,'height =',sizey

 

 

Ответ 4

Вот моя версия:

def getTerminalSize():

    """

    returns (lines:int, cols:int)

    """

    import os, struct

    def ioctl_GWINSZ(fd):

        import fcntl, termios

        return struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))

    # try stdin, stdout, stderr

    for fd in (0, 1, 2):

        try:

            return ioctl_GWINSZ(fd)

        except:

            pass

    # try os.ctermid()

    try:

        fd = os.open(os.ctermid(), os.O_RDONLY)

        try:

            return ioctl_GWINSZ(fd)

        finally:

            os.close(fd)

    except:

        pass

    # try `stty size`

    try:

        return tuple(int(x) for x in os.popen("stty size", "r").read().split())

    except:

        pass

    # try environment variables

    try:

        return tuple(int(os.getenv(var)) for var in ("LINES", "COLUMNS"))

    except:

        pass

    # i give up. return default.

    return (25, 80)

 

Ответ 5

Если вы используете Python 3.3 или выше, я бы рекомендовал использовать встроенную функцию get_terminal_size(). Однако, если вы используете более старую версию и хотите получить простой кроссплатформенный способ сделать это, вы можете использовать пакет asciimatics. Этот пакет поддерживает версии Python вплоть до 2.7 и использует опции, аналогичные предложенным выше, для получения текущего размера терминала/консоли.

Просто создайте свой класс Screen и используйте свойство dimensions для получения высоты и ширины. Было установлено, что это работает в Linux, OSX и Windows.

 

Схожие статьи

Disable path length limit при установке Python: что это
Python

Disable path length limit при установке Python: что это

5 лучших языков программирования для детей
Python

5 лучших языков программирования для детей

Игровой движок на Python: тестовая, консольная игра
Python

Игровой движок на Python: тестовая, консольная игра

Путь к мастерству: создаём приложение-словарь на Python
Python

Путь к мастерству: создаём приложение-словарь на Python