apt like column output -pythonライブラリ
-
22-09-2019 - |
質問
DebianのAPTツール出力は、均一な幅の列になります。たとえば、「適性検索SVN」を実行してみてください。すべての名前が同じ幅の最初の列に表示されます。
これで、端子をサイズ変更すると、列の幅がそれに応じて調整されます。
これを行うことを可能にするPythonライブラリはありますか?ライブラリは端末の幅を認識し、入力としてテーブルを取る必要があることに注意してください。 [('rapidsvn', 'A GUI client for subversion'), ...]
..また、最初の列(または列)の最大幅を指定することもできます。また、端子幅を超えると、下の2番目の列の文字列がトリミングされる方法に注意してください。したがって、望ましくない2行目を導入しないことに注意してください。
$ aptitude search svn
[...]
p python-svn-dbg - A(nother) Python interface to Subversion (d
v python2.5-svn -
v python2.6-svn -
p rapidsvn - A GUI client for subversion
p statsvn - SVN repository statistics
p svn-arch-mirror - one-way mirroring from Subversion to Arch r
p svn-autoreleasedeb - Automatically release/upload debian package
p svn-buildpackage - helper programs to maintain Debian packages
p svn-load - An enhanced import facility for Subversion
p svn-workbench - A Workbench for Subversion
p svnmailer - extensible Subversion commit notification t
p websvn - interface for subversion repositories writt
$
編集: :(以下のAlexの回答に応じて)...出力は1)最後の列(これは連続して最も長い文字列を持つ唯一の列です)のみをトリミングすることです。 )通常、2〜4列のみがありますが、最後の列(「説明」)は端子幅の少なくとも半分をとると予想されます。 3)すべての行には同数の列が含まれ、4)すべてのエントリは文字列のみです
解決
「ターミナルの幅を取得する」ための一般的なクロスプラットフォームの方法はないと思います - 間違いなくそうではありません 「列環境変数を見てください」(質問に関する私のコメントを参照)。 LinuxとMac OS X(そして、私はすべての最新のUNIXバージョンを期待しています)、
curses.wrapper(lambda _: curses.tigetnum('cols'))
列数を返します。しかし、私は知りません wcurses これをWindowsでサポートします。
(os.environ ['columns']から(culse」、または呪いを介して、またはオラクルを介して、またはデフォルトの80、またはその他の好みの方法で)を持っていると、残りは非常に実行可能です。それはFinnickyの仕事であり、オフ1種類のエラーの可能性が多く、あなたが完全に明確にしていない多くの詳細な仕様に対して非常に脆弱です:そのように、どの列がラッピングを避けるためにカットされます - それは常にそれを最後のもの、または...?質問に従って2つだけが渡された場合、サンプル出力に3つの列を表示するにはどうして?すべての行が同じ列の列を持っていない場合、何が起こるはずですか?テーブルのすべてのエントリは文字列でなければなりませんか?そして、この同類の他の多くの謎。
したがって、あなたが表現していないすべての仕様のためにやや基本的な推測をすると、1つのアプローチは次のようなものかもしれません...:
import sys
def colprint(totwidth, table):
numcols = max(len(row) for row in table)
# ensure all rows have >= numcols columns, maybe empty
padded = [row+numcols*('',) for row in table]
# compute col widths, including separating space (except for last one)
widths = [ 1 + max(len(x) for x in column) for column in zip(*padded)]
widths[-1] -= 1
# drop or truncate columns from the right in order to fit
while sum(widths) > totwidth:
mustlose = sum(widths) - totwidth
if widths[-1] <= mustlose:
del widths[-1]
else:
widths[-1] -= mustlose
break
# and finally, the output phase!
for row in padded:
for w, i in zip(widths, row):
sys.stdout.write('%*s' % (-w, i[:w]))
sys.stdout.write('\n')
他のヒント
アップデート: : colprint
ルーチンは、で利用可能になりました アプリブ Pythonライブラリ Githubでホスト.
これが興味のある方のための完全なプログラムです:
# This function was written by Alex Martelli
# http://stackoverflow.com/questions/1396820/
def colprint(table, totwidth=None):
"""Print the table in terminal taking care of wrapping/alignment
- `table`: A table of strings. Elements must not be `None`
- `totwidth`: If None, console width is used
"""
if not table: return
if totwidth is None:
totwidth = find_console_width()
totwidth -= 1 # for not printing an extra empty line on windows
numcols = max(len(row) for row in table)
# ensure all rows have >= numcols columns, maybe empty
padded = [row+numcols*('',) for row in table]
# compute col widths, including separating space (except for last one)
widths = [ 1 + max(len(x) for x in column) for column in zip(*padded)]
widths[-1] -= 1
# drop or truncate columns from the right in order to fit
while sum(widths) > totwidth:
mustlose = sum(widths) - totwidth
if widths[-1] <= mustlose:
del widths[-1]
else:
widths[-1] -= mustlose
break
# and finally, the output phase!
for row in padded:
print(''.join([u'%*s' % (-w, i[:w])
for w, i in zip(widths, row)]))
def find_console_width():
if sys.platform.startswith('win'):
return _find_windows_console_width()
else:
return _find_unix_console_width()
def _find_unix_console_width():
"""Return the width of the Unix terminal
If `stdout` is not a real terminal, return the default value (80)
"""
import termios, fcntl, struct, sys
# fcntl.ioctl will fail if stdout is not a tty
if not sys.stdout.isatty():
return 80
s = struct.pack("HHHH", 0, 0, 0, 0)
fd_stdout = sys.stdout.fileno()
size = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
height, width = struct.unpack("HHHH", size)[:2]
return width
def _find_windows_console_width():
"""Return the width of the Windows console
If the width cannot be determined, return the default value (80)
"""
# http://code.activestate.com/recipes/440694/
from ctypes import windll, create_string_buffer
STDIN, STDOUT, STDERR = -10, -11, -12
h = windll.kernel32.GetStdHandle(STDERR)
csbi = create_string_buffer(22)
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
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
else:
sizex, sizey = 80, 25
return sizex
まあ、適性は使用します cwidget
テキストのみのディスプレイの列をフォーマットします。あなたは電話することができます cwidget
Python拡張機能を作成しますが、それはトラブルの価値があるとは思いません...実際の水平サイズをcharsで取得して自分自身を計算するという好みの方法を使用できます。
まず、使用します ioctl
TTYのサイズを取得するには:
import termios, fcntl, struct, sys
def get_tty_size():
s = struct.pack("HHHH", 0, 0, 0, 0)
fd_stdout = sys.stdout.fileno()
size = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
return struct.unpack("HHHH", size)[:2]
print get_tty_size()
次に、このような関数を使用して列を作成します。
pad = lambda s, n=20: "%s%s" % (s,' '*(n-len(s)))
それらをまとめると、コンソールのサイズ変更列があります!