在python中是否有一种方法以编程方式确定控制台的宽度?我指的是一行中不换行的字符数,而不是窗口的像素宽度。
编辑
寻找在Linux上工作的解决方案
使用
import console (width, height) = console.getTerminalSize() print "Your terminal's width is: %d" % width
编辑:哦,对不起。这不是python标准库,这里是console.py的源代码(我不知道它来自哪里)。
termcap
ioctl
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])
import os rows, columns = os.popen('stty size', 'r').read().split()
使用'stty size'命令,根据python邮件列表中的一个线程,该命令在linux上相当通用。它打开“stty size”命令作为文件,从中“读取”,并使用一个简单的字符串分割来分隔坐标。
不像操作系统。environ["COLUMNS"]值(尽管使用bash作为我的标准shell,但我不能访问),数据也将是最新的,而我相信os。environ["COLUMNS"]值只在python解释器启动时有效(假设用户自那时起调整了窗口的大小)。
(参见@GringoSuave关于如何在python 3.3+上做到这一点的回答)
上面的代码在我的linux上没有返回正确的结果,因为winsize-struct有4个unsigned shorts,而不是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和HP应该包含像素的宽度和高度,但不是。
看起来代码有点问题,Johannes:
getTerminalSize
import os
env
os.environ
另外,为什么在返回之前切换lines和cols ?如果TIOCGWINSZ和stty都说lines,那么cols,我说就这样吧。这让我困惑了10分钟,直到我注意到这种不一致。
lines
cols
TIOCGWINSZ
stty
Sridhar,我在管道输出时没有得到这个错误。我很确定它在尝试中被正确地捕获了——除了。
"HHHH"不能在我的机器上工作,但是"hh"可以。我很难找到这个函数的文档。它看起来依赖于平台。
"HHHH"
"hh"
chochem,合并。
以下是我的看法:
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)
下面是一个应该与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')
我四处寻找,找到了窗户的解决方案:
http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/ < a href = " http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/ " > < / >
这里有一个Linux的解决方案。
下面是一个在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
不确定为什么它在模块shutil中,但它在Python 3.3中出现在那里。看到的:
shutil
查询输出终端的大小 .输出终端的大小
>>> import shutil >>> shutil.get_terminal_size((80, 20)) # pass fallback os.terminal_size(columns=87, lines=23) # returns a named-tuple
底层实现在os模块中。跨平台工作在Linux, Mac OS和Windows,可能是其他unix类。还有一个后端口,虽然已经无关紧要了。
>>> import os >>> ts = os.get_terminal_size() >>> ts.lines 24 >>> ts.columns 80
@reannual的答案很好,但有一个问题:os.popen 现在已弃用。应该使用subprocess模块,所以这里有一个使用subprocess的@reannual代码版本,并直接回答了这个问题(通过直接将列宽度作为int:
os.popen
subprocess
int
import subprocess columns = int(subprocess.check_output(['stty', 'size']).split()[1])
在OS X 10.9上测试
我正在尝试从这里调用stty size的解决方案:
stty size
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
然而,这对我来说失败了,因为我正在编写一个脚本,期望在stdin上重定向输入,而stty会抱怨“stdin不是终端”在这种情况下。
我能做到这样:
with open('/dev/tty') as tty: height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
尝试“祝福”
我也在找同样的东西。它非常易于使用,并提供了在终端中着色、造型和定位的工具。你需要的很简单:
from blessings import Terminal t = Terminal() w = t.width h = t.height
在Linux中工作就像一个魅力。(我不确定MacOSX和Windows)
下载和文档在这里
或者你可以用pip安装它:
pip install blessings
如果你使用的是Python 3.3或更高版本,我建议使用内置的get_terminal_size()。然而,如果你被一个旧版本所困,想要一个简单的,跨平台的方式来做这件事,你可以使用asciimatics。这个包支持2.7以下的Python版本,并使用与上面建议的选项类似的选项来获取当前终端/控制台大小。
get_terminal_size()
简单地构造你的Screen类,并使用dimensions属性来获取高度和宽度。这已经在Linux、OSX和Windows上被证明是有效的。
Screen
dimensions
哦,在这里完全披露:我是作者,所以如果你在这方面有任何问题,请随时打开一个新的问题。
如果在调用此脚本时没有控制终端,那么这里的许多Python 2实现都将失败。您可以检查sys.stdout.isatty()来确定这是否实际上是一个终端,但这将排除一些情况,因此我认为最python化的方法来计算终端大小是使用内置的curses包。
import curses w = curses.initscr() height, width = w.getmaxyx()
它是:
import os columns, rows = os.get_terminal_size(0) # or import shutil columns, rows = shutil.get_terminal_size()
os
os.get_terminal_size(0)
第一个参数0是一个参数,指示应该使用stdin文件描述符而不是默认的stdout。我们希望使用stdin,因为stdout在被管道传输时会分离自身,在这种情况下会引发错误。
0
我试图弄清楚什么时候使用stdout而不是stdin参数是有意义的,不知道为什么它是这里的默认值。