pythonにコンソールの幅をプログラムで決定する方法はありますか?ウィンドウのピクセル幅ではなく、折り返さずに1行に収まる文字数を意味します。
編集
Linuxで動作するソリューションを探しています
import os
rows, columns = os.popen('stty size', 'r').read().split()
pythonメーリングリストのスレッド によれば、Linuxではかなり汎用的な「stty size」コマンドを使用します。 「stty size」コマンドをファイルとして開き、「読み取り」、単純な文字列分割を使用して座標を分離します。
Os.environ ["COLUMNS"]値(標準のシェルとしてbashを使用しているにもかかわらずアクセスできない)とは異なり、os.environ ["COLUMNS"]を信じているのにデータも最新のものになります。値はpythonインタープリターの起動時のみ有効です(それ以降、ユーザーがウィンドウのサイズを変更したと仮定します)。
なぜそれがモジュール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
低レベルの実装はosモジュールにあります。
バックポートがPython 3.2以下で利用可能になりました。
つかいます
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
EDIT:ああ、ごめんなさい。これはpython標準ライブラリの1つではなく、console.pyのソースです(どこから来たのかわかりません)。
モジュールはそのように動作するようです:はいの場合、termcap
が利用可能かどうかをチェックします。それを使用します。 noの場合、端末が特別な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])
上記のコードは、私のLinuxでは正しい結果を返しませんでした。なぜなら、winsize-structには、2つの署名されたショートではなく、4つの署名されていないショートがあるからです。
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のソリューションはこちら。
だから、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 __== "__main__":
sizex,sizey=getTerminalSize()
print 'width =',sizex,'height =',sizey
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
次のいずれかです。
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
shutil
関数は、いくつかのエラーをキャッチしてフォールバックを設定するos
関数の単なるラッパーですが、1つの大きな警告があります-パイピングすると壊れます! 、これは非常に大きな問題です。
パイピング時に端子サイズを取得するには、代わりにos.get_terminal_size(0)
を使用します。
最初の引数0
は、デフォルトのstdoutの代わりにstdinファイル記述子を使用する必要があることを示す引数です。 stdoutがパイプされているときにstdoutがそれ自体をデタッチするため、stdinを使用します。この場合、エラーが発生します。
stdin引数の代わりにstdoutを使用するのが理にかなっているのはいつかを考えてみましたが、なぜここでデフォルトになるのかわかりません。
そのコードにはいくつかの問題があるようです、ヨハネス:
getTerminalSize
はimport os
にする必要がありますenv
とは何ですか? os.environ
のように見えます。また、戻る前にlines
とcols
を切り替えるのはなぜですか? TIOCGWINSZ
とstty
の両方がlines
に続いてcols
と言う場合、そのままにしておきます。これにより、矛盾に気付く前に10分間混乱しました。
Sridhar、出力をパイプしたときにそのエラーは発生しませんでした。 try-exceptで適切にキャッチされていると確信しています。
Pascal、"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)
このスクリプトを呼び出すときに制御端末がない場合、ここのPython 2実装の多くは失敗します。 sys.stdout.isatty()をチェックして、これが実際に端末であるかどうかを判断できますが、これは多くの場合を除外するため、端末サイズを判断する最もPython的な方法は組み込みのcursesパッケージを使用することです。
import curses
w = curses.initscr()
height, width = w.getmaxyx()
私はここから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()
Python 3.3以降を使用している場合、既に推奨されているように、組み込みのget_terminal_size()
をお勧めします。ただし、古いバージョンにこだわっており、これを行うためのシンプルでクロスプラットフォームな方法が必要な場合は、 asciimatics を使用できます。このパッケージはPythonのバージョン2.7をサポートし、上記と同様のオプションを使用して現在のターミナル/コンソールサイズを取得します。
Screen
クラスを構築し、dimensions
プロパティを使用して高さと幅を取得するだけです。これは、Linux、OSX、およびWindowsで動作することが実証されています。
ああ-ここに完全に開示されています:私は著者ですので、これを機能させるのに問題がある場合は、気軽に新しい問題を開いてください。
@reannualの答えはうまくいきますが、問題があります:os.popen
現在廃止予定 。代わりにsubprocess
モジュールを使用する必要があります。したがって、これはsubprocess
を使用し、質問に直接回答する(列幅をint
として直接指定する)@reannualのコードのバージョンです。
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
OS X 10.9でテスト済み
試してみてください "blessings"
私はまったく同じものを探していました。非常に使いやすく、ターミナルでの色付け、スタイリング、および配置のためのツールを提供します。必要なものは簡単です:
from blessings import Terminal
t = Terminal()
w = t.width
h = t.height
Linuxの魅力のように機能します。 (MacOSXとWindowsについてはわかりません)
ダウンロードとドキュメント こちら
または、pipでインストールできます。
pip install blessings
LinuxおよびSolarisと互換性のあるバージョンを以下に示します。 madchine からの投稿とコメントに基づいています。サブプロセスモジュールが必要です。
def termsize(): import shlex、サブプロセス、re output = subprocess.check_output(shlex.split( '/ bin/stty -a')) m = re.search( 'rows\D +(?P\d +); columns\D +(?P\d +);'、出力) if m: return m.group( 'rows')、m.group( 'columns') raise OSError( 'Bad response:%s'%(output))
>>> termsize() ( '40'、 '100')