Pythonでコンソールの幅をプログラムで決定する方法はありますか?つまり、ウィンドウのピクセル幅ではなく、折り返さずに1行に収まる文字数を意味します。
編集する
Linuxで動作するソリューションを探しています
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インタープリターの起動時のみ有効です(それ以降、ユーザーがウィンドウのサイズを変更したとします)。
(Python 3.3以降でこれを行う方法については@GringoSuaveの回答を参照してください)
rows, columns = subprocess.check_output(['stty', 'size']).split()
少し短く、さらにサブプロセスが未来
rows, columns = subprocess.check_output(['stty', 'size']).decode().split()
py2 / 3互換性のためにUnicode文字列が必要な場合
なぜそれがモジュールにあるのかはわかりませんが、出力ターミナルのサイズをクエリ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モジュールにあります。Windowsでも動作します。
バックポートがPython 3.2以下で利用可能になりました:
python3.5
インストールされています。
Inappropriate ioctl for device
エラー/警告を、または80の定義されたフォールバック値を取得
使用する
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
編集:ああ、ごめんなさい。これはpython標準のlibのものではありません。ここに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にはピクセルの幅と高さが含まれている必要がありますが、含まれていません。
fcntl.ioctl(sys.stdin.fileno(), ...
stdout
またはを使用する必要があると思います。パイプかもしれません。のような行を追加することもできます。stderr
stdin
stdin
if not os.isatty(0): return float("inf")
私は周りを検索して、Windowsの解決策を見つけました:
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
次のいずれかです。
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ファイル記述子を使用する必要があることを示す引数です。stdinは、パイプ処理されているときに自身を切り離すため、stdinを使用します。この場合、エラーが発生します。
stdin引数の代わりにstdoutを使用することが理にかなっている場合を理解しようとしましたが、なぜこれがデフォルトであるのかわかりません。
os.get_terminal_size()
Python 3.3で導入されました
os.get_terminal_size(0)
stdinにパイプすると、を使用するとクラッシュします。試してみる:echo x | python3 -c 'import os; print(os.get_terminal_size(0))'
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
shutil.get_terminal_size() is the high-level function which should normally be used, os.get_terminal_size is the low-level implementation.
そのコードにはいくつかの問題があるようです、ヨハネス:
getTerminalSize
する必要があります import os
env
?のように見えますos.environ
。また、なぜ切り替えるlines
とcols
返す前に?場合TIOCGWINSZ
とstty
の両方が言うlines
そしてcols
、私はそのように残して言います。これは、私が矛盾に気付く前に10分間混乱させました。
Sridhar、出力をパイプ処理したときにエラーが発生しませんでした。私はそれがtry-exceptで適切にキャッチされていると確信しています。
パスカル、"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)
私はここから呼び出しを行う解決策を試していました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
@reannualの回答は適切に機能しますが、問題があります:os.popen
は非推奨になりました。subprocess
モジュールはので、ここで使用していること@ reannualのコードのバージョンですが、代わりに使用する必要がありますsubprocess
直接として直接列幅を与えることによって(質問に答えるにはint
:
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
OS X 10.9でテスト済み
Python 3.3以降を使用している場合は、組み込みをget_terminal_size()
お勧めします。ただし、古いバージョンで立ち往生していて、これを行う単純なクロスプラットフォームの方法が必要な場合は、asciimaticsを使用できます。このパッケージは2.7までのバージョンのPythonをサポートし、上記のオプションと同様のオプションを使用して、現在のターミナル/コンソールサイズを取得します。
Screen
クラスを作成し、dimensions
プロパティを使用して高さと幅を取得するだけです。これは、Linux、OSX、Windowsで動作することが証明されています。
ああ、ここで完全に開示します:私は著者です。これを機能させるのに問題がある場合は、新しい問題を自由に開いてください。
これは、LinuxとSolarisの互換性があるバージョンです。以下からの投稿とcommmentsに基づきmadchine。サブプロセスモジュールが必要です。
def termsize(): shlex、サブプロセス、reのインポート output = subprocess.check_output(shlex.split( '/ bin / stty -a')) m = re.search( 'rows \ D +(?P \ d +); columns \ D +(?P \ d +);'、output) mの場合: m.group( 'rows')、m.group( 'columns')を返します OSErrorを発生させる( '不正な応答:%s'%(出力))
>>> termsize() ( '40'、 '100')