如何在Python中获得Linux控制台窗口宽度

时间:2022-05-12 20:46:03

Is there a way in python to programmatically determine the width of the console? I mean the number of characters that fits in one line without wrapping, not the pixel width of the window.

python中是否有一种方法以编程方式确定控制台的宽度?我指的是在一行中不需要换行的字符数,而不是窗口的像素宽度。

Edit

编辑

Looking for a solution that works on Linux

寻找在Linux上工作的解决方案

14 个解决方案

#1


219  

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

uses the 'stty size' command which according to a thread on the python mailing list is reasonably universal on linux. It opens the 'stty size' command as a file, 'reads' from it, and uses a simple string split to separate the coordinates.

使用“stty size”命令,根据python邮件列表中的一个线程,该命令在linux上是通用的。它将“stty size”命令作为一个文件打开,“读取”它,并使用一个简单的字符串分割来分离坐标。

Unlike the os.environ["COLUMNS"] value (which I can't access in spite of using bash as my standard shell) the data will also be up-to-date whereas I believe the os.environ["COLUMNS"] value would only be valid for the time of the launch of the python interpreter (suppose the user resized the window since then).

与操作系统。环境[“列”]值(尽管使用bash作为标准shell,但我无法访问它)数据也将是最新的,而我相信操作系统。环境["COLUMNS"]值仅在python解释器启动时才有效(假设从那时起用户调整窗口的大小)。

#2


176  

Not sure why it is in the module shutil, but it landed there in Python 3.3, Querying the size of the output terminal:

不知道为什么会出现在shutil模块中,但它在Python 3.3中出现,查询输出终端的大小:

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

A low-level implementation is in the os module.

操作系统模块中有一个底层实现。

A backport is now available for Python 3.2 and below:

Python 3.2和以下版本现在有一个支持端口:

#3


65  

use

使用

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

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

EDIT: oh, I'm sorry. That's not a python standard lib one, here's the source of console.py (I don't know where it's from).

编辑:哦,我很抱歉。这不是一个python标准库,这里是控制台的来源。py(我不知道是从哪里来的)。

The module seems to work like that: It checks if termcap is available, when yes. It uses that; if no it checks whether the terminal supports a special ioctl call and that does not work, too, it checks for the environment variables some shells export for that. This will probably work on UNIX only.

这个模块看起来是这样工作的:它检查termcap是否可用,当是。它使用;如果没有,它会检查终端是否支持一个特殊的ioctl调用,而这也不起作用,它会检查一些shell导出的环境变量。这可能只适用于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])

#4


48  

Code above didn't return correct result on my linux because winsize-struct has 4 unsigned shorts, not 2 signed shorts:

上面的代码在我的linux上没有返回正确的结果,因为winsistruct有4个无符号短裤,而不是2个有符号短裤:

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 and hp should contain pixel width and height, but don't.

hp和hp应该包含像素的宽度和高度,但是不要。

#5


35  

I searched around and found a solution for windows at :

我找遍了四周,找到了windows的解决方案:

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

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

and a solution for linux here.

这里是linux的一个解决方案。

So here is a version which works both on linux, os x and windows/cygwin :

这是一个在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://*.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

#6


15  

Starting at Python 3.3 it is straight forward: https://docs.python.org/3/library/os.html#querying-the-size-of-a-terminal

从Python 3.3开始,它是直接向前的:https://docs.python.org/3/library/os.html#query -the- of-a-terminal

>>> import os
>>> ts = os.get_terminal_size()
>>> ts.lines
24
>>> ts.columns
80

#7


6  

It looks like there are some problems with that code, Johannes:

约翰内斯,看起来这段代码有些问题:

  • getTerminalSize needs to import os
  • getTerminalSize需要导入os
  • what is env? looks like os.environ.
  • env是什么?看起来像os.environ。

Also, why switch lines and cols before returning? If TIOCGWINSZ and stty both say lines then cols, I say leave it that way. This confused me for a good 10 minutes before I noticed the inconsistency.

还有,为什么在回来之前换线和cols呢?如果TIOCGWINSZ和stty都说台词,那么cols,我就这么说。这让我困惑了10分钟,然后我才注意到这种不一致。

Sridhar, I didn't get that error when I piped output. I'm pretty sure it's being caught properly in the try-except.

Sridhar,当我输出管道时,我没有得到那个错误。我很确定它在试戴中被正确地抓住了——除了。

pascal, "HHHH" doesn't work on my machine, but "hh" does. I had trouble finding documentation for that function. It looks like it's platform dependent.

帕斯卡"HHHH"在我的机器上不能用,但"hh"可以用。我找不到那个函数的文档。它看起来是依赖于平台的。

chochem, incorporated.

chochem,合并。

Here's my version:

这是我的版本:

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)

#8


5  

Many of the Python 2 implementations here will fail if there is no controlling terminal when you call this script. You can check sys.stdout.isatty() to determine if this is in fact a terminal, but that will exclude a bunch of cases, so I believe the most pythonic way to figure out the terminal size is to use the builtin curses package.

如果在调用此脚本时没有控制终端,那么这里的许多Python 2实现都将失败。您可以检查sys.stdout.isatty()以确定这是否是一个终端,但这将排除一些情况,因此我认为,计算终端大小的最python化的方法是使用内置的curses包。

import curses
w = curses.initscr()
height, width = w.getmaxyx()

#9


4  

It's either:

它是:

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

The shutil function is just a wrapper around os one that catches some errors and set up a fallback, however it has one huge caveat - it breaks when piping!, which is a pretty huge deal.
To have get terminal size when piping use os.get_terminal_size(0) instead.

shutil函数只是os 1的一个包装器,它捕获了一些错误并设置了一个回退,但是它有一个巨大的警告——当管道连接时它会崩溃!这是一笔很大的交易。当管道使用os.get_terminal_size(0)来获取终端大小。

First argument 0 is an argument indicating that stdin file descriptor should be used instead of default stdout. We want to use stdin because stdout detaches itself when it is being piped which raises in this case raises an error..
I've tried to figure out when would it makes sense to use stdout instead of stdin argument and have no idea why it a default here.

第一个参数0是一个参数,指示应该使用stdin文件描述符而不是默认的stdout。我们想要使用stdin,因为stdout在管道中被管道输送时,它会自动断开。我试图弄清楚何时使用stdout而不是stdin参数是有意义的,我不知道为什么这里是默认值。

#10


1  

@reannual's answer works well, but there's an issue with it: os.popen is now deprecated. The subprocess module should be used instead, so here's a version of @reannual's code that uses subprocess and directly answers the question (by giving the column width directly as an int:

@reannual的回答很好,但有一个问题:os。popen现在已经弃用。应该使用子过程模块,所以这里有一个版本的@reannual代码,它使用子过程并直接回答问题(通过将列宽度直接作为int形式给出):

import subprocess

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

Tested on OS X 10.9

在OS X 10.9上测试。

#11


1  

I was trying the solution from here that calls out to stty size:

我正在尝试从这里开始的解决方案,它要求stty尺寸:

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

However this failed for me because I was working on a script that expects redirected input on stdin, and stty would complain that "stdin isn't a terminal" in that case.

然而,这对我来说是失败的,因为我正在编写一个脚本,希望在stdin上重定向输入,而stty会抱怨“stdin不是终端”。

I was able to make it work like this:

我能让它像这样工作:

with open('/dev/tty') as tty:
    height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()

#12


1  

Try "blessings"

试着“祝福”

I was looking for the very same thing. It is very easy to use and offers tools for coloring, styling and positioning in the terminal. What you need is as easy as:

我在找同样的东西。它非常容易使用,并提供工具的着色,造型和定位在终端。你所需要的就是:

from blessings import Terminal

t = Terminal()

w = t.width
h = t.height

Works like a charm in Linux. (I'm not sure about MacOSX and Windows)

在Linux中工作就像一个魔咒。(我对MacOSX和Windows不太确定)

Download and documentation here

在这里下载和文档

or you can install it with pip:

也可以安装pip:

pip install blessings

#13


1  

If you're using Python 3.3 or above, I'd recommend the built-in get_terminal_size() as already recommended. However if you are stuck with an older version and want a simple, cross-platform way of doing this, you could use asciimatics. This package supports versions of Python back to 2.7 and uses similar options to those suggested above to get the current terminal/console size.

如果您正在使用Python 3.3或更高版本,我建议您使用已经推荐的内置get_terminal_size()。但是,如果你坚持使用一个旧版本,并且想要一个简单的跨平台的方法,你就可以使用海怪。这个包支持Python的版本回到2.7,并使用类似的选项来获得当前终端/控制台的大小。

Simply construct your Screen class and use the dimensions property to get the height and width. This has been proven to work on Linux, OSX and Windows.

只需构造屏幕类,并使用dimensions属性获取高度和宽度。这已经在Linux、OSX和Windows上得到了证明。

Oh - and full disclosure here: I am the author, so please feel free to open a new issue if you have any problems getting this to work.

哦,这里有一个完整的披露:我是作者,所以如果你有任何问题,请打开一个新的问题,使这工作。

#14


0  

Here is an version that should be Linux and Solaris compatible. Based on the posts and commments from madchine. Requires the subprocess module.

这是一个应该与Linux和Solaris兼容的版本。根据来自madchine的帖子和评论。要求子流程模块。

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

#1


219  

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

uses the 'stty size' command which according to a thread on the python mailing list is reasonably universal on linux. It opens the 'stty size' command as a file, 'reads' from it, and uses a simple string split to separate the coordinates.

使用“stty size”命令,根据python邮件列表中的一个线程,该命令在linux上是通用的。它将“stty size”命令作为一个文件打开,“读取”它,并使用一个简单的字符串分割来分离坐标。

Unlike the os.environ["COLUMNS"] value (which I can't access in spite of using bash as my standard shell) the data will also be up-to-date whereas I believe the os.environ["COLUMNS"] value would only be valid for the time of the launch of the python interpreter (suppose the user resized the window since then).

与操作系统。环境[“列”]值(尽管使用bash作为标准shell,但我无法访问它)数据也将是最新的,而我相信操作系统。环境["COLUMNS"]值仅在python解释器启动时才有效(假设从那时起用户调整窗口的大小)。

#2


176  

Not sure why it is in the module shutil, but it landed there in Python 3.3, Querying the size of the output terminal:

不知道为什么会出现在shutil模块中,但它在Python 3.3中出现,查询输出终端的大小:

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

A low-level implementation is in the os module.

操作系统模块中有一个底层实现。

A backport is now available for Python 3.2 and below:

Python 3.2和以下版本现在有一个支持端口:

#3


65  

use

使用

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

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

EDIT: oh, I'm sorry. That's not a python standard lib one, here's the source of console.py (I don't know where it's from).

编辑:哦,我很抱歉。这不是一个python标准库,这里是控制台的来源。py(我不知道是从哪里来的)。

The module seems to work like that: It checks if termcap is available, when yes. It uses that; if no it checks whether the terminal supports a special ioctl call and that does not work, too, it checks for the environment variables some shells export for that. This will probably work on UNIX only.

这个模块看起来是这样工作的:它检查termcap是否可用,当是。它使用;如果没有,它会检查终端是否支持一个特殊的ioctl调用,而这也不起作用,它会检查一些shell导出的环境变量。这可能只适用于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])

#4


48  

Code above didn't return correct result on my linux because winsize-struct has 4 unsigned shorts, not 2 signed shorts:

上面的代码在我的linux上没有返回正确的结果,因为winsistruct有4个无符号短裤,而不是2个有符号短裤:

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 and hp should contain pixel width and height, but don't.

hp和hp应该包含像素的宽度和高度,但是不要。

#5


35  

I searched around and found a solution for windows at :

我找遍了四周,找到了windows的解决方案:

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

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

and a solution for linux here.

这里是linux的一个解决方案。

So here is a version which works both on linux, os x and windows/cygwin :

这是一个在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://*.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

#6


15  

Starting at Python 3.3 it is straight forward: https://docs.python.org/3/library/os.html#querying-the-size-of-a-terminal

从Python 3.3开始,它是直接向前的:https://docs.python.org/3/library/os.html#query -the- of-a-terminal

>>> import os
>>> ts = os.get_terminal_size()
>>> ts.lines
24
>>> ts.columns
80

#7


6  

It looks like there are some problems with that code, Johannes:

约翰内斯,看起来这段代码有些问题:

  • getTerminalSize needs to import os
  • getTerminalSize需要导入os
  • what is env? looks like os.environ.
  • env是什么?看起来像os.environ。

Also, why switch lines and cols before returning? If TIOCGWINSZ and stty both say lines then cols, I say leave it that way. This confused me for a good 10 minutes before I noticed the inconsistency.

还有,为什么在回来之前换线和cols呢?如果TIOCGWINSZ和stty都说台词,那么cols,我就这么说。这让我困惑了10分钟,然后我才注意到这种不一致。

Sridhar, I didn't get that error when I piped output. I'm pretty sure it's being caught properly in the try-except.

Sridhar,当我输出管道时,我没有得到那个错误。我很确定它在试戴中被正确地抓住了——除了。

pascal, "HHHH" doesn't work on my machine, but "hh" does. I had trouble finding documentation for that function. It looks like it's platform dependent.

帕斯卡"HHHH"在我的机器上不能用,但"hh"可以用。我找不到那个函数的文档。它看起来是依赖于平台的。

chochem, incorporated.

chochem,合并。

Here's my version:

这是我的版本:

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)

#8


5  

Many of the Python 2 implementations here will fail if there is no controlling terminal when you call this script. You can check sys.stdout.isatty() to determine if this is in fact a terminal, but that will exclude a bunch of cases, so I believe the most pythonic way to figure out the terminal size is to use the builtin curses package.

如果在调用此脚本时没有控制终端,那么这里的许多Python 2实现都将失败。您可以检查sys.stdout.isatty()以确定这是否是一个终端,但这将排除一些情况,因此我认为,计算终端大小的最python化的方法是使用内置的curses包。

import curses
w = curses.initscr()
height, width = w.getmaxyx()

#9


4  

It's either:

它是:

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

The shutil function is just a wrapper around os one that catches some errors and set up a fallback, however it has one huge caveat - it breaks when piping!, which is a pretty huge deal.
To have get terminal size when piping use os.get_terminal_size(0) instead.

shutil函数只是os 1的一个包装器,它捕获了一些错误并设置了一个回退,但是它有一个巨大的警告——当管道连接时它会崩溃!这是一笔很大的交易。当管道使用os.get_terminal_size(0)来获取终端大小。

First argument 0 is an argument indicating that stdin file descriptor should be used instead of default stdout. We want to use stdin because stdout detaches itself when it is being piped which raises in this case raises an error..
I've tried to figure out when would it makes sense to use stdout instead of stdin argument and have no idea why it a default here.

第一个参数0是一个参数,指示应该使用stdin文件描述符而不是默认的stdout。我们想要使用stdin,因为stdout在管道中被管道输送时,它会自动断开。我试图弄清楚何时使用stdout而不是stdin参数是有意义的,我不知道为什么这里是默认值。

#10


1  

@reannual's answer works well, but there's an issue with it: os.popen is now deprecated. The subprocess module should be used instead, so here's a version of @reannual's code that uses subprocess and directly answers the question (by giving the column width directly as an int:

@reannual的回答很好,但有一个问题:os。popen现在已经弃用。应该使用子过程模块,所以这里有一个版本的@reannual代码,它使用子过程并直接回答问题(通过将列宽度直接作为int形式给出):

import subprocess

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

Tested on OS X 10.9

在OS X 10.9上测试。

#11


1  

I was trying the solution from here that calls out to stty size:

我正在尝试从这里开始的解决方案,它要求stty尺寸:

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

However this failed for me because I was working on a script that expects redirected input on stdin, and stty would complain that "stdin isn't a terminal" in that case.

然而,这对我来说是失败的,因为我正在编写一个脚本,希望在stdin上重定向输入,而stty会抱怨“stdin不是终端”。

I was able to make it work like this:

我能让它像这样工作:

with open('/dev/tty') as tty:
    height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()

#12


1  

Try "blessings"

试着“祝福”

I was looking for the very same thing. It is very easy to use and offers tools for coloring, styling and positioning in the terminal. What you need is as easy as:

我在找同样的东西。它非常容易使用,并提供工具的着色,造型和定位在终端。你所需要的就是:

from blessings import Terminal

t = Terminal()

w = t.width
h = t.height

Works like a charm in Linux. (I'm not sure about MacOSX and Windows)

在Linux中工作就像一个魔咒。(我对MacOSX和Windows不太确定)

Download and documentation here

在这里下载和文档

or you can install it with pip:

也可以安装pip:

pip install blessings

#13


1  

If you're using Python 3.3 or above, I'd recommend the built-in get_terminal_size() as already recommended. However if you are stuck with an older version and want a simple, cross-platform way of doing this, you could use asciimatics. This package supports versions of Python back to 2.7 and uses similar options to those suggested above to get the current terminal/console size.

如果您正在使用Python 3.3或更高版本,我建议您使用已经推荐的内置get_terminal_size()。但是,如果你坚持使用一个旧版本,并且想要一个简单的跨平台的方法,你就可以使用海怪。这个包支持Python的版本回到2.7,并使用类似的选项来获得当前终端/控制台的大小。

Simply construct your Screen class and use the dimensions property to get the height and width. This has been proven to work on Linux, OSX and Windows.

只需构造屏幕类,并使用dimensions属性获取高度和宽度。这已经在Linux、OSX和Windows上得到了证明。

Oh - and full disclosure here: I am the author, so please feel free to open a new issue if you have any problems getting this to work.

哦,这里有一个完整的披露:我是作者,所以如果你有任何问题,请打开一个新的问题,使这工作。

#14


0  

Here is an version that should be Linux and Solaris compatible. Based on the posts and commments from madchine. Requires the subprocess module.

这是一个应该与Linux和Solaris兼容的版本。根据来自madchine的帖子和评论。要求子流程模块。

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