Есть ли в Python способ программно определить ширину консоли? Я имею в виду количество символов, которые помещаются в одну строку без переноса, а не ширину окна в пикселях.
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 (предположим, что пользователь изменил размер окна с тех пор).
(Смотрите ответ @GringoSuave о том, как это сделать на Python 3.3+)
Вы можете заставить это работать и в Solaris, если вместо «size» вы передадите «-a». В выходных данных, разделенных точкой с запятой, будет "row = Y; columns = X".
Джозеф Гарвин
5
COLUMNS не экспортируется по умолчанию в Bash, поэтому os.environ ["COLUMNS"] не работает.
Это потому, что вы не должны больше использовать 2.7, сделайте переход на 3.x, это того стоит.
anthonyryan1
5
@osirisgothra Многие хостинг-провайдеры пока не поддерживают python3, поэтому некоторые из нас вынуждены использовать python2 для серверной разработки. Хотя это не должно иметь ничего общего с получением размера терминала ...
whitebeard
4
@osirisgothra Потому что есть много кода Python 2, для переноса которого потребуется слишком много работы. Кроме того, Pypy все еще имеет слабую поддержку Python 3.
Сурьма
2
@whitebeard Есть ли причина, по которой подписчик не может установить Python 3 на VPS? Или в 2016 году люди все еще используют виртуальный хостинг, администратор которого не хочет устанавливать Python 3? Например, установлен общий хостинг WebFaction python3.5.
Дамиан Йеррик
2
+1 за решение, которое также работает, когда стандартный ввод был перенаправлен из файла! С другими решениями я либо получал сообщения об Inappropriate ioctl for deviceошибках / предупреждениях, либо получал определенное запасное значение 80.
pawamoy
65
использование
import console
(width, height)= console.getTerminalSize()print"Your terminal's width is: %d"% width
РЕДАКТИРОВАТЬ : о, я извиняюсь. Это не стандартная библиотека Python, вот источник console.py (я не знаю, откуда он).
Модуль, кажется, работает так: он проверяет, termcapдоступен ли, когда да. Это использует это; если нет, он проверяет, поддерживает ли терминал специальный ioctlвызов, и это тоже не работает, он проверяет переменные среды, которые некоторые оболочки экспортируют для этого. Это, вероятно, будет работать только в UNIX.
Спасибо за быстрый ответ, но здесь ( effbot.org/zone/console-handbook.htm ) говорится, что «Модуль консоли в настоящее время доступен только для Windows 95, 98, NT и 2000». Я ищу решение, которое работает на Linux. Вероятно, это не было ясно из тега, я отредактирую вопрос соответственно.
Сергей Головченко
2
поскольку используемый вами «консольный» модуль не входит в стандартную библиотеку python, вы должны предоставить его исходный код или хотя бы ссылку на него.
nosklo
Я так сожалею об этом. На самом деле, я не знал этот модуль. Я попытался импортировать консоль, и она работала, я использовал консоль. <Tab> <tab> и getTerminalSize () обнаружились. Вместо того, чтобы искать, откуда он, я уже опубликовал ответ, потому что мне так повезло в простоте. G
Йоханнес Вайс,
Возможно, я смотрю на другой «консольный» модуль, не могли бы вы предоставить ссылку на тот, который у вас есть?
Сергей Головченко
4
Да, и не для того, чтобы накапливать код, но "cr" - это запутанное имя, потому что оно подразумевает, что кортеж есть (столбцы, строки). На самом деле, все наоборот.
Пол Дю Буа
57
Приведенный выше код не дал верного результата в моем linux, потому что winsize-struct имеет 4 шорта без знака, а не 2 шорта со знаком:
Вот как это должно быть сделано; обратите внимание, что если вы собираетесь печатать в терминал, вы должны использовать '1' в качестве дескриптора файла (первый аргумент ioctl), так как stdin может быть каналом или каким-то другим tty.
mic_e
1
Возможно, 0 следует заменить наfcntl.ioctl(sys.stdin.fileno(), ...
raylu
4
это лучший ответ - ваши пользователи будут рады, что не будет неожиданного подпроцесса, происходящего только для того, чтобы получить ширину термина
zzzeek
4
это действительно самый чистый ответ. Я думаю, что вы должны использовать stdoutили stderrвместо stdin, хотя. stdinвполне может быть труба. Вы также можете добавить строку, например if not os.isatty(0): return float("inf").
mic_e
это как-то работает на терминале Chromebook, который не имеет никакой функциональности. +1
Эта shutilфункция является просто оберткой вокруг osтой, которая ловит некоторые ошибки и устанавливает запасной вариант, однако имеет одно огромное предостережение - она ломается при прокачке! Это довольно большое дело.
Чтобы получить размер терминала при использовании трубопровода, используйте os.get_terminal_size(0)вместо этого.
Первый аргумент 0- это аргумент, указывающий, что дескриптор файла stdin должен использоваться вместо стандартного stdout. Мы хотим использовать stdin, потому что stdout отключается, когда он передается по каналу, что в этом случае вызывает ошибку.
Я попытался выяснить, когда имеет смысл использовать stdout вместо аргумента stdin, и понятия не имею, почему это значение по умолчанию.
os.get_terminal_size()был представлен в Python 3.3
villapx
Сначала я попробовал шутил, и это сработало с первой попытки. Я использую Python 3.6+.
Дан
Использование os.get_terminal_size(0)приведет к сбою, если вы отправите трубку на стандартный ввод Попробуйте:echo x | python3 -c 'import os; print(os.get_terminal_size(0))'
shutil.get_terminal_size() is the high-level function which should normally be used, os.get_terminal_size is the low-level implementation.
mid_kid
1
Это почти копия ответа на год старше, приведенного выше.
Гринго Суаве
6
Похоже, с этим кодом есть некоторые проблемы, Йоханнес:
getTerminalSize нуждается в import os
что такое env? выглядит как os.environ.
Также зачем переключаться linesи colsдо возвращения? Если TIOCGWINSZи то , и sttyдругое говорят linesтогда cols, я говорю, оставь это так. Это смутило меня на целых 10 минут, прежде чем я заметил несоответствие.
Шридхар, я не получил эту ошибку, когда передал вывод. Я почти уверен, что это правильно поймано в попытке.
Паскаль, "HHHH"не работает на моей машине, но "hh"работает. У меня были проблемы с поиском документации для этой функции. Похоже, это зависит от платформы.
Хохем, включены.
Вот моя версия:
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, stderrfor 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 variablestry:return tuple(int(os.getenv(var))for var in("LINES","COLUMNS"))except:pass# i give up. return default.return(25,80)
Я envтоже бродил по этому поводу , и это действительно env = os.environот принятого ответа .
sdaau
6
Многие из реализаций Python 2 здесь потерпят неудачу, если при вызове этого скрипта не будет управляющего терминала. Вы можете проверить sys.stdout.isatty (), чтобы определить, является ли это на самом деле терминалом, но это исключит кучу случаев, поэтому я считаю, что самый питонный способ выяснить размер терминала - это использовать встроенный пакет curses.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
Однако это не помогло мне, потому что я работал над сценарием, который ожидает перенаправленного ввода на stdin, и sttyжаловался бы, что в этом случае «stdin не терминал».
Я смог заставить его работать так:
with open('/dev/tty')as tty:
height, width = subprocess.check_output(['stty','size'], stdin=tty).split()
Я искал то же самое. Он очень прост в использовании и предлагает инструменты для окраски, укладки и позиционирования в терминале. То, что вам нужно, так же просто, как:
from blessings importTerminal
t =Terminal()
w = t.width
h = t.height
Работает как шарм в Linux. (Я не уверен насчет MacOSX и Windows)
В настоящее время я бы сказал, попробуйте "благословенный", который является в настоящее время поддерживаемым форком (и улучшением) "благословений".
Зезолло
1
Ответ @ reannual работает хорошо, но есть проблема с ним: os.popenтеперь устарела . subprocessМодуль должен использоваться вместо этого, так вот версия @ reannual код , который использует subprocessи непосредственно отвечает на вопрос (давая ширину столбца непосредственно как int:
Если вы используете Python 3.3 или выше, я бы порекомендовал встроенный, get_terminal_size()как уже рекомендовано. Однако, если вы застряли в более старой версии и хотите простой кроссплатформенный способ сделать это, вы можете использовать asciimatics . Этот пакет поддерживает версии Python до 2.7 и использует опции, аналогичные предложенным выше, чтобы получить текущий размер терминала / консоли.
Просто создайте свой Screenкласс и используйте dimensionsсвойство, чтобы получить высоту и ширину. Доказано, что это работает на Linux, OSX и Windows.
О - и полное раскрытие здесь: я автор, поэтому, пожалуйста, не стесняйтесь открывать новый выпуск, если у вас есть какие-либо проблемы, чтобы заставить это работать.
Ответы:
использует команду 'stty size', которая, согласно потоку в списке рассылки python, является достаточно универсальной в linux. Он открывает команду «stty size» в виде файла, «читает» из нее и использует простое разбиение строки для разделения координат.
В отличие от значения os.environ ["COLUMNS"] (к которому я не могу получить доступ, несмотря на использование bash в качестве стандартной оболочки), данные также будут современными, тогда как я считаю, что os.environ ["COLUMNS"] Значение будет действительным только для времени запуска интерпретатора Python (предположим, что пользователь изменил размер окна с тех пор).
(Смотрите ответ @GringoSuave о том, как это сделать на Python 3.3+)
источник
rows, columns = subprocess.check_output(['stty', 'size']).split()
немного короче, плюс подпроцесс - будущееrows, columns = subprocess.check_output(['stty', 'size']).decode().split()
Если вам нужны строки в кодировке Юникод для совместимости с py2 / 3Не уверен, почему он находится в модуле
shutil
, но он приземлился там в Python 3.3, запрашивая размер выходного терминала :Низкоуровневая реализация находится в модуле os. Также работает в Windows.
Бэкпорт теперь доступен для Python 3.2 и ниже:
источник
python3.5
.Inappropriate ioctl for device
ошибках / предупреждениях, либо получал определенное запасное значение 80.использование
РЕДАКТИРОВАТЬ : о, я извиняюсь. Это не стандартная библиотека Python, вот источник console.py (я не знаю, откуда он).
Модуль, кажется, работает так: он проверяет,
termcap
доступен ли, когда да. Это использует это; если нет, он проверяет, поддерживает ли терминал специальныйioctl
вызов, и это тоже не работает, он проверяет переменные среды, которые некоторые оболочки экспортируют для этого. Это, вероятно, будет работать только в UNIX.источник
Приведенный выше код не дал верного результата в моем linux, потому что winsize-struct имеет 4 шорта без знака, а не 2 шорта со знаком:
hp и hp должны содержать ширину и высоту пикселя, но не должны.
источник
fcntl.ioctl(sys.stdin.fileno(), ...
stdout
илиstderr
вместоstdin
, хотя.stdin
вполне может быть труба. Вы также можете добавить строку, напримерif not os.isatty(0): return float("inf")
.Я искал вокруг и нашел решение для Windows на:
http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/
и решение для Linux здесь.
Итак, вот версия, которая работает как на Linux, OS X и Windows / Cygwin:
источник
Это либо:
Эта
shutil
функция является просто оберткой вокругos
той, которая ловит некоторые ошибки и устанавливает запасной вариант, однако имеет одно огромное предостережение - она ломается при прокачке! Это довольно большое дело.Чтобы получить размер терминала при использовании трубопровода, используйте
os.get_terminal_size(0)
вместо этого.Первый аргумент
0
- это аргумент, указывающий, что дескриптор файла stdin должен использоваться вместо стандартного stdout. Мы хотим использовать stdin, потому что stdout отключается, когда он передается по каналу, что в этом случае вызывает ошибку.Я попытался выяснить, когда имеет смысл использовать stdout вместо аргумента stdin, и понятия не имею, почему это значение по умолчанию.
источник
os.get_terminal_size()
был представлен в Python 3.3os.get_terminal_size(0)
приведет к сбою, если вы отправите трубку на стандартный ввод Попробуйте:echo x | python3 -c 'import os; print(os.get_terminal_size(0))'
Начиная с Python 3.3, это просто: https://docs.python.org/3/library/os.html#querying-the-size-of-a-terminal
источник
shutil.get_terminal_size() is the high-level function which should normally be used, os.get_terminal_size is the low-level implementation.
Похоже, с этим кодом есть некоторые проблемы, Йоханнес:
getTerminalSize
нуждается вimport os
env
? выглядит какos.environ
.Также зачем переключаться
lines
иcols
до возвращения? ЕслиTIOCGWINSZ
и то , иstty
другое говорятlines
тогдаcols
, я говорю, оставь это так. Это смутило меня на целых 10 минут, прежде чем я заметил несоответствие.Шридхар, я не получил эту ошибку, когда передал вывод. Я почти уверен, что это правильно поймано в попытке.
Паскаль,
"HHHH"
не работает на моей машине, но"hh"
работает. У меня были проблемы с поиском документации для этой функции. Похоже, это зависит от платформы.Хохем, включены.
Вот моя версия:
источник
env
тоже бродил по этому поводу , и это действительноenv = os.environ
от принятого ответа .Многие из реализаций Python 2 здесь потерпят неудачу, если при вызове этого скрипта не будет управляющего терминала. Вы можете проверить sys.stdout.isatty (), чтобы определить, является ли это на самом деле терминалом, но это исключит кучу случаев, поэтому я считаю, что самый питонный способ выяснить размер терминала - это использовать встроенный пакет curses.
источник
Я пробовал решение отсюда, которое призывает
stty size
:Однако это не помогло мне, потому что я работал над сценарием, который ожидает перенаправленного ввода на stdin, и
stty
жаловался бы, что в этом случае «stdin не терминал».Я смог заставить его работать так:
источник
Попробуйте "благословения"
Я искал то же самое. Он очень прост в использовании и предлагает инструменты для окраски, укладки и позиционирования в терминале. То, что вам нужно, так же просто, как:
Работает как шарм в Linux. (Я не уверен насчет MacOSX и Windows)
Скачать и документацию здесь
или вы можете установить его с помощью pip:
источник
Ответ @ reannual работает хорошо, но есть проблема с ним:
os.popen
теперь устарела .subprocess
Модуль должен использоваться вместо этого, так вот версия @ reannual код , который используетsubprocess
и непосредственно отвечает на вопрос (давая ширину столбца непосредственно какint
:Протестировано на OS X 10.9
источник
Если вы используете Python 3.3 или выше, я бы порекомендовал встроенный,
get_terminal_size()
как уже рекомендовано. Однако, если вы застряли в более старой версии и хотите простой кроссплатформенный способ сделать это, вы можете использовать asciimatics . Этот пакет поддерживает версии Python до 2.7 и использует опции, аналогичные предложенным выше, чтобы получить текущий размер терминала / консоли.Просто создайте свой
Screen
класс и используйтеdimensions
свойство, чтобы получить высоту и ширину. Доказано, что это работает на Linux, OSX и Windows.О - и полное раскрытие здесь: я автор, поэтому, пожалуйста, не стесняйтесь открывать новый выпуск, если у вас есть какие-либо проблемы, чтобы заставить это работать.
источник
Вот версия, которая должна быть совместима с Linux и Solaris. Основано на сообщениях и комментариях от Madchine . Требуется модуль подпроцесса.
источник