Jak uzyskać szerokość okna konsoli Linuksa w Pythonie

Czy jest sposób w Pythonie aby programowo określić szerokość konsoli? Mam na myśli liczbę znaków, które mieszczą się w jednej linii bez zawijania, a nie Szerokość pikseli okna.

Edit

Szukam rozwiązania, które działa na Linuksie

Author: anatoly techtonik, 2009-02-19

14 answers

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

Używa polecenia 'stty size', które zgodnie z wątek na liście dyskusyjnej Pythona jest dość uniwersalny w Linuksie. Otwiera polecenie "rozmiar stty" jako plik, "odczytuje" z niego i używa prostego podziału łańcuchów, aby oddzielić współrzędne.

W przeciwieństwie do os.wartość environ["COLUMNS"] (do której nie mogę uzyskać dostępu pomimo używania Basha jako standardowej powłoki) dane będą również aktualne, podczas gdy wierzę, że system operacyjny.wartość environ["COLUMNS"] będzie ważna tylko przez czas uruchomienie interpretera Pythona (Załóżmy, że od tego czasu użytkownik zmienił rozmiar okna).

 226
Author: brokkr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-03 10:06:54

Nie wiem, dlaczego jest w module shutil, ale wylądował tam w Pythonie 3.3, pytając o rozmiar terminala wyjściowego :

>>> import shutil
>>> shutil.get_terminal_size((80, 20))  # pass fallback
os.terminal_size(columns=87, lines=23)  # returns a named-tuple

Implementacja niskiego poziomu znajduje się w module systemu operacyjnego.

Backport jest teraz dostępny dla Pythona 3.2 i poniżej:

 188
Author: Gringo Suave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-30 17:45:29

Użyj

import console
(width, height) = console.getTerminalSize()

print "Your terminal's width is: %d" % width

EDIT : przepraszam. To nie jest standardowy lib Pythona, oto źródło console.py (Nie wiem skąd pochodzi).

Moduł wydaje się działać w ten sposób: sprawdza, czy termcap jest dostępny, gdy tak. Używa tego; jeśli nie, sprawdza, czy terminal obsługuje specjalne wywołanie ioctl i to również nie działa, sprawdza, czy zmienne środowiskowe eksportują do tego niektóre powłoki. To prawdopodobnie będzie działać tylko na Uniksie.

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))

        ### Use get(key[, default]) instead of a try/catch
        #try:
        #    cr = (env['LINES'], env['COLUMNS'])
        #except:
        #    cr = (25, 80)
    return int(cr[1]), int(cr[0])
 65
Author: Johannes Weiss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-14 19:38:02

Powyższy kod nie zwrócił poprawnego wyniku na moim Linuksie, ponieważ winsize-struct ma 4 unsigned shorts, a nie 2 signed shorts:

def terminal_size():
    import fcntl, termios, struct
    h, w, hp, wp = struct.unpack('HHHH',
        fcntl.ioctl(0, termios.TIOCGWINSZ,
        struct.pack('HHHH', 0, 0, 0, 0)))
    return w, h

Hp i hp powinny zawierać szerokość i wysokość pikseli, ale nie powinny.

 49
Author: pascal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-09 22:36:38

Szukałem i znalazłem rozwiązanie dla windows pod adresem:

Http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/

I rozwiązanie dla Linuksa tutaj.

Oto wersja, która działa zarówno na Linuksie, os x i 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()
          # needed for window's python in 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():
    # get terminal width
    # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window
    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
 35
Author: Harco Kuppens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-05 09:22:23

Począwszy od Pythona 3.3 jest prosto: https://docs.python.org/3/library/os.html#querying-the-size-of-a-terminal

>>> import os
>>> ts = os.get_terminal_size()
>>> ts.lines
24
>>> ts.columns
80
 15
Author: Bob Enohp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-27 23:24:31

Wygląda na to, że są pewne problemy z tym kodem, Johannes:

  • getTerminalSize musi import os
  • co to jest env? wygląda na os.environ.

Również, po co przełączać lines i cols przed powrotem? Jeśli TIOCGWINSZ i stty oba mówią lines, to cols, mówię zostawić to w ten sposób. To zdezorientowało mnie przez dobre 10 minut, zanim zauważyłem niespójność.

Sridhar, nie dostałem tego błędu, gdy rurociągiem wyjście. Jestem prawie pewien, że jest dobrze złapany w spróbuj-z wyjątkiem.

Pascal, "HHHH" nie działa na mojej maszynie, ale "hh" Działa. Miałem problem ze znalezieniem dokumentacji dla tej funkcji. Wygląda na to, że jest zależny od platformy.

Chochem, incorporated.

Oto moja wersja:

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)
 6
Author: thejoshwolfe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 07:23:51

Wiele implementacji Pythona 2 tutaj zawiedzie, jeśli nie ma kontrolującego terminala podczas wywoływania tego skryptu. Możesz sprawdzić sys.stdout.isatty (), aby określić, czy jest to terminal, ale to wyklucza kilka przypadków, więc uważam, że najbardziej pythonicznym sposobem na ustalenie rozmiaru terminala jest użycie wbudowanego pakietu curses.

import curses
w = curses.initscr()
height, width = w.getmaxyx()
 6
Author: wonton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-31 22:26:04

Jest albo:

import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()

Funkcja shutil jest tylko owijarką wokół os, która wychwytuje pewne błędy i ustawia rezerwę, jednak ma jedno ogromne zastrzeżenie- pęka podczas orurowania!, co jest całkiem sporą sprawą.
Aby uzyskać rozmiar terminala podczas rurociągu, użyj os.get_terminal_size(0).

Pierwszy argument 0 jest argumentem wskazującym, że deskryptor pliku stdin powinien być używany zamiast domyślnego stdout. Chcemy używać stdin, ponieważ stdout odłącza się, gdy jest piped, który podnosi w tym przypadku powoduje błąd..
Próbowałem dowiedzieć się, kiedy ma sens używanie stdout zamiast argumentu stdin i nie mam pojęcia, dlaczego jest to tutaj Domyślne.

 5
Author: Granitosaurus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 04:51:39

[[5]]@re: odpowiedź działa dobrze, ale jest z tym problem: os.popen jest obecnie przestarzały . Zamiast tego powinien być użyty moduł subprocess, więc oto wersja kodu @re annual, który używa subprocess i odpowiada bezpośrednio na pytanie (podając szerokość kolumny bezpośrednio jako int:

import subprocess

columns = int(subprocess.check_output(['stty', 'size']).split()[1])

Testowane na OS X 10.9

 1
Author: rickcnagy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-22 18:30:16

Próbowałem stąd rozwiązania, które wywołuje stty size:

columns = int(subprocess.check_output(['stty', 'size']).split()[1])

Jednak nie udało mi się to, ponieważ pracowałem nad skryptem, który oczekuje przekierowanego wejścia na stdin i stty narzekałbym, że "stdin nie jest terminalem" w tym przypadku.

Udało mi się to zrobić tak:

with open('/dev/tty') as tty:
    height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
 1
Author: Marc Liyanage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-08 18:36:32

Try"blessings"

Szukałam tego samego. Jest bardzo łatwy w użyciu i oferuje narzędzia do kolorowania, stylizacji i pozycjonowania w terminalu. To, czego potrzebujesz, jest tak proste, jak:
from blessings import Terminal

t = Terminal()

w = t.width
h = t.height

Działa jak urok w Linuksie. (Nie jestem pewien co do MacOSX i Windows)

Pobierz i dokumentację tutaj

Lub możesz go zainstalować za pomocą pip:

pip install blessings
 1
Author: Iman Akbari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-23 12:00:41

Jeśli używasz Pythona 3.3 lub nowszego, polecam wbudowany get_terminal_size() jako już zalecany. Jeśli jednak utknąłeś w starszej wersji i chcesz zrobić to w prosty, wieloplatformowy sposób, możesz użyć asciimatics. Ten pakiet obsługuje wersje Pythona z powrotem do 2.7 i używa podobnych opcji do tych sugerowanych powyżej, aby uzyskać bieżący rozmiar terminala / konsoli.

Po prostu zbuduj klasę Screen i użyj właściwości dimensions, aby uzyskać wysokość i szerokość. To ma udowodniono, że działa na Linuksie, OSX i Windows.

Oh-i pełne ujawnienie tutaj: jestem autorem, więc proszę, nie krępuj się otworzyć nowy numer, jeśli masz jakiekolwiek problemy z doprowadzeniem tego do pracy.

 1
Author: Peter Brittain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-24 09:54:50

Oto wersja, która powinna być kompatybilna z Linuksem i Solarisem. Na podstawie postów i komentarzy z madchine . Wymaga modułu podprocesu.

def termsize():
    import shlex, subprocess, re
    output = subprocess.check_output(shlex.split('/bin/stty -a'))
    m = re.search('rows\D+(?P\d+); columns\D+(?P\d+);', output)
    if m:
        return m.group('rows'), m.group('columns')
    raise OSError('Bad response: %s' % (output))
>>> termsize()
('40', '100')
 0
Author: Derrick Petzold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:19