[python] 파이썬에서 리눅스 콘솔 창 너비를 얻는 방법

파이썬에서 콘솔의 너비를 프로그래밍 방식으로 결정하는 방법이 있습니까? 나는 창의 픽셀 너비가 아니라 줄 바꿈없이 한 줄에 맞는 문자 수를 의미합니다.

편집하다

Linux에서 작동하는 솔루션을 찾고



답변

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

파이썬 메일 링리스트의 스레드에 따라 ‘stty size’명령을 사용합니다 . 리눅스에서는 합리적입니다. ‘stty size’명령을 파일로 열고 파일에서 읽은 다음 간단한 문자열 분할을 사용하여 좌표를 구분합니다.

os.environ [ “COLUMNS”] 값과 달리 (표준 쉘로 bash를 사용하더라도 액세스 할 수 없음) 데이터도 최신 상태이지만 os.environ [ “COLUMNS”] 값은 파이썬 인터프리터가 시작된 시간에만 유효합니다 (그 이후로 사용자가 창 크기를 조정했다고 가정하십시오).

(python 3.3 이상 에서이 작업을 수행하는 방법에 대한 @GringoSuave의 답변 참조)


답변

왜 모듈에 있는지 shutil모르지만 파이썬 3.3에 도착 하여 출력 터미널의 크기를 쿼리합니다 .

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

저수준 구현은 os 모듈에 있습니다. Windows에서도 작동합니다.

백 포트는 이제 Python 3.2 이하에서 사용 가능합니다 :


답변

사용하다

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

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

편집 : 아, 죄송합니다. 그것은 파이썬 표준 라이브러리가 아닙니다. 여기서 console.py 소스가 있습니다 (어디에서 왔는지 모르겠습니다).

모듈은 다음과 같이 작동하는 것 같습니다 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))

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


답변

winsize-struct에는 2 개의 부호있는 반바지가 아닌 4 개의 부호없는 반바지가 있기 때문에 위의 코드는 Linux에서 올바른 결과를 반환하지 않았습니다.

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와 hp는 픽셀 너비와 높이를 포함해야하지만 그렇지 않습니다.


답변

나는 주변에서 검색하고 창문에 대한 해결책을 찾았습니다.

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

여기에 리눅스 솔루션이 있습니다.

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


답변

다음 중 하나입니다.

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

shutil기능은 os약간의 오류를 포착하고 폴백을 설정 하는 래퍼입니다 . 그러나 한 가지 큰 경고가 있습니다 . , 이것은 꽤 큰 거래입니다.
배관시 터미널 크기를 얻으려면 os.get_terminal_size(0)대신 사용하십시오.

첫 번째 주장 0 는 기본 stdout 대신 stdin 파일 디스크립터를 사용해야 함을 나타내는 입니다. stdin이 파이프 될 때 자체가 분리 되어이 경우 오류가 발생하기 때문에 stdin을 사용하려고합니다.

나는 stdin 인수 대신 stdout을 사용하는 것이 언제 의미가 있는지 알아 내려고 왜 이것이 기본값인지 알지 못했습니다.


답변

Python 3.3부터는 다음과 같이 간단합니다.
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