2012-03-01 3 views
4

これはPythonプログラマのための質問です。 MySQLdbクエリの結果を人間が読める形式で出力するには、どのように知っていますか? mysqlシェルによって出力されたテーブルと似たものが素晴らしいでしょう。MySQLdbのユニコード結果を人間が読める形式で出力するには

ような何か:

+-----+---------------------+-----------+ 
| id | now()    | aaa  | 
+-----+---------------------+-----------+ 
| 28 | 2012-03-01 14:24:02 | some text | 
| 77 | 2012-03-01 14:24:02 | some text | 
| 89 | 2012-03-01 14:24:02 | some text | 
| 114 | 2012-03-01 14:24:02 | some text | 
| 116 | 2012-03-01 14:24:02 | some text | 
| 252 | 2012-03-01 14:24:02 | some text | 
+-----+---------------------+-----------+ 

重要な注意:言語は必ずしも英語ではないとして、それは、ユニコードでなければなりません。 ありがとうございます!

例:

のMySql一部:

create table test.tmp_ids(id integer); 
insert into test.tmp_ids values (28),(77),(89),(114),(116),(252); 

のpythonコード:

cursor = db.cursor() 
cursor.execute("select id, now(), 'some text' as aaa from test.tmp_ids") 
rows = cursor.fetchall() 
print rows <<<<<<<<<<< here instead of just "print rows" I would like to print it as a human-readable table. 
+0

私は[Format String Syntax](http://docs.python.org/library/string.html#formatstrings)を使用することができますね。 – jensgram

+1

はい、すべての列の長さをすべて知る必要があります。それのための準備ができている機能はありますか? – diemacht

+0

表示方法の例を追加してください:) – Nilesh

答えて

3

のような出力が得られます。この

a = '''<% 
    rows = [[v for v in range(0,10)] for row in range(0,10)] 
%> 
<table border="1"> 
    % for row in rows: 
     ${makerow(row)} 
    % endfor 
</table> 

<%def name="makerow(row)"> 
    <tr> 
     % for name in row: 
      <td>${name}</td> 
     % endfor 
    </tr> 
</%def> 
</td> 
''' 
from mako.template import Template 

x = open('/tmp/test.html', 'w') 
x.write(Template(a).render()) 
x.close() 

import commands 
a, b = commands.getstatusoutput('links -dump 1 /tmp/test.html') 
print b 

を試してみて、モノスペースフォントでさえ、すべてのユニコードを同じ幅で表示するようには見えません(例については以下を参照してください)。

それにも関わらず、George Sakkis's table indentation recipe上のこの変化は十分である:ファイルtable.py

保存この:

import operator 
import itertools 
import re 
import math 
import functools 
import logging 
logger = logging.getLogger(__name__) 

zip_longest = itertools.izip_longest 

def tableinfo(rows, 
       sep = u'─', 
       corner = u'·', 
       delim = None, 
       corner_delim = None, 
       prefix = u'│ ', 
       postfix = u' │', 
       colsep = u' │ ', 
       has_header = False, 
       header = None, 
       separate_rows = False, 
       framed = (True, True), 
       separate_empty_lines = True, 
       justify = 'right', 
       wrapfunc = lambda x:x, 
       width = None, 
       phantom = None, 
       **kw): 
    # Based on: http://code.activestate.com/recipes/267662-table-indentation/ 
    # Author: http://code.activestate.com/recipes/users/2591466/ (George Sakkis) 
    def row_wrapper(row): 
     try: 
      new_rows = [wrapper(item).split('\n') for (item, wrapper) 
         in zip(row, wrapfunc)] 
     except TypeError: 
      # This happens if wrapfunc is not an iterator 
      # TypeError: zip argument #2 must support iteration 
      new_rows = [wrapfunc(item).split('\n') for item in row] 
     return list(zip_longest(*new_rows, fillvalue = u'')) 
    if header: 
     has_header = True 
     rows = itertools.chain(normalize([header]), rows) 
    logical_rows = [row_wrapper(row) for row in rows] 
    columns = zip(*functools.reduce(operator.add, logical_rows)) 
    max_width = (
     [max(len(item) for item in column) for column in columns] 
     if width is None else width) 
    if phantom is not None: 
     max_width = [max(x) for x in zip(phantom, max_width)] 
    lcorner = corner + sep*(len(prefix)-1) if len(prefix) >= 1 else u'' 
    rcorner = sep*(len(postfix)-1) + corner if len(postfix) >= 1 else u'' 

    delim = itertools.repeat(colsep) if delim is None else itertools.cycle(delim) 
    corner_delim = (delim_to_corner(delim, sep, corner) 
        if corner_delim is None else itertools.cycle(corner_delim))  
    row_separator = (sep*w for w in max_width) 
    row_separator = (lcorner 
        +''.join(list(iterjoin(corner_delim, row_separator))) 
        +rcorner) 
    dispatch = {'center':unicode.center, 'right':unicode.rjust, 'left':unicode.ljust} 
    try: justify = itertools.cycle([dispatch[item] for item in justify]) 
    except KeyError: justify = itertools.repeat(dispatch[justify.lower()]) 
    result = [] 
    for physical_rows in logical_rows: 
     row_result = [] 
     for row in physical_rows: 
      if separate_empty_lines and not ''.join(row).strip(): 
       row_result.append(row_separator) 
      else: 
       pieces = [justifier(item, w) for (item, w, justifier) 
         in zip(row, max_width, justify)] 
       row_result.append(
        prefix 
        + u''.join(list(iterjoin(delim, pieces))) 
        + postfix)     
     result.append(u'\n'.join(row_result)) 
     if has_header and not separate_rows: 
      result.insert(1, row_separator) 
      has_header = False 
    joiner = u'\n'+row_separator+u'\n' if separate_rows else u'\n' 
    result = joiner.join(result) 
    top_framed, bottom_framed = framed 
    if top_framed: result = row_separator+u'\n'+result 
    if bottom_framed: result = result+u'\n'+row_separator 
    return result, max_width 

def iterjoin(sep, it): 
    sep = itertools.cycle(sep) 
    it = iter(it) 
    yield next(it) 
    for a, b in zip(it, sep): 
     yield b 
     yield a 

def normalize(rows): 
    new_rows = [] 
    for row in rows: 
     new_rows.append([unicode(elt).expandtabs() for elt in row]) 
    return new_rows 

def delim_to_corner(delim, sep, corner): 
    for d in delim: 
     d = d.replace(u'│', corner).replace(u'|', corner) 
     for c in '< >': d = d.replace(c, sep) 
     yield d 

def wrap_onspace(text, width): 
    # written by Mike Brown 
    # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061 
    ''' 
    A word-wrap function that preserves existing line breaks 
    and most spaces in the text. Expects that existing line 
    breaks are posix newlines (\n). 
    ''' 
    words = iter(text.split(' ')) 
    line = next(words) 
    for word in words: 
     contemplated_width = (len(line[line.rfind('\n')+1:]) + 
           len(word.split('\n', 1)[0])) 
     if contemplated_width >= width: 
      line += '\n'+word 
     else: 
      line += ' '+word 
    return line 

def wrap_onspace_strict(text, width): 
    '''Similar to wrap_onspace, but enforces the width constraint: 
     words longer than width are split.''' 
    word_pat = re.compile(r'\S{'+unicode(width)+r',}') 
    return wrap_onspace(word_pat.sub(lambda m: wrap_always(m.group(), width), text), 
         width) 

def wrap_always(text, width): 
    '''A simple word-wrap function that wraps text on exactly width characters. 
     It doesn\'t split the text in words.''' 
    return '\n'.join(text[width*i:width*(i+1)] 
         for i in xrange(int(math.ceil(1.*len(text)/width)))) 

def onspace(width): 
    return functools.partial(wrap_onspace, width = width) 

def strict(width): 
    return functools.partial(wrap_onspace_strict, width = width) 

def always(width): 
    return functools.partial(wrap_always, width = width) 

def table(rows, 
      sep = u'─', 
      corner = u'·', 
      delim = None, 
      corner_delim = None, 
      prefix = u'│ ', 
      postfix = u' │', 
      has_header = False, 
      header = None, 
      separate_rows = False, 
      framed = (True, True), 
      separate_empty_lines = True, 
      justify = 'right', 
      wrapfunc = lambda x:x, 
      width = None, 
      **kw): 
    ''' 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │     rows │ A sequence of sequences of items, one sequence per row. │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    framed │ row separator on top and bottom       │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │     sep │ Character to be used for the row separator line (if  │ 
    │      │ has_header==True or separate_rows==True).    │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    delim │ A sequence of column delimiters. The delimiters are  │ 
    │      │ repeated in a cycle          │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │   corner_delim │ A sequence of column delimiters used in row separators, │ 
    │      │ repeated in a cycle.         │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    prefix │ A string prepended to each printed row.     │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    postfix │ A string appended to each printed row.     │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │   has_header │ True if there is a row separator between the first and │ 
    │      │ second row            │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │  separate_rows │ True if all rows are to be separated     │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    framed │ True if top (and/or bottom) have a row separator  │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │ separate_empty_lines │ replace empty lines with a row separator    │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    justify │ Determines how the data is justified in each column. │ 
    │      │ Valid values are 'left','right' and 'center', or a list │ 
    │      │ of such values (one element per column).    │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    wrapfunc │ A function f(text), or list of functions, for wrapping │ 
    │      │ text; each element in the table is first wrapped by  │ 
    │      │ this function. If wrapfunc is a list of functions, then │ 
    │      │ table will apply one function per column.    │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    │    width │ A list of column widths. If None, the widths will be │ 
    │      │ calculated.            │ 
    ·──────────────────────·─────────────────────────────────────────────────────────· 
    ''' 
    result, max_width = tableinfo(
     normalize(rows), sep = sep, corner = corner, delim = delim, 
     corner_delim = corner_delim, 
     prefix = prefix, postfix = postfix, has_header = has_header, header = header, 
     separate_rows = separate_rows, framed = framed, 
     separate_empty_lines = separate_empty_lines, justify = justify, 
     wrapfunc = wrapfunc, width = width) 
    return result 

def ascii_table(rows, 
      sep = '-', 
      corner = '+', 
      delim = [' | '], 
      corner_delim = None, 
      prefix = u'| ', 
      postfix = u' |', 
      has_header = False, 
      header = None, 
      separate_rows = False, 
      framed = (True, True), 
      separate_empty_lines = True, 
      justify = 'right', 
      wrapfunc = lambda x:x, 
      width = None, 
      **kw): 
    result, max_width = tableinfo(
     normalize(rows), sep = sep, corner = corner, delim = delim, 
     corner_delim = corner_delim, 
     prefix = prefix, postfix = postfix, has_header = has_header, header = header, 
     separate_rows = separate_rows, framed = framed, 
     separate_empty_lines = separate_empty_lines, justify = justify, 
     wrapfunc = wrapfunc, width = width) 
    return result 

その後、あなたはこのようにそれを使用することができます:

を生み出す

import table 

data = [ 
    ('id', 'now()', 'aaa'), 
    ('28', '2012-03-01 14:24:02', u'To \N{INFINITY} and beyond'), 
    ('77', '2012-03-01 14:24:02', u"All with me's meet"), 
    ('89', '2012-03-01 14:24:02', u' that I can fashion fit \N{BLACK SMILING FACE}'), 
    ('114', '2012-03-01 14:24:02', u'\N{LATIN CAPITAL LETTER OU}'), 
    ('116', '2012-03-01 14:24:02', u'An extra wide unicode: \N{COMBINING CYRILLIC HUNDRED THOUSANDS SIGN}'), 
    ('252', '2012-03-01 14:24:02', u'\N{THEREFORE}'), 
    ] 

print(table.ascii_table(data, has_header = True)) 

+-----+---------------------+---------------------------+ 
| id |    now() |      aaa | 
+-----+---------------------+---------------------------+ 
| 28 | 2012-03-01 14:24:02 |   To ∞ and beyond | 
| 77 | 2012-03-01 14:24:02 |  All with me's meet | 
| 89 | 2012-03-01 14:24:02 | that I can fashion fit ☻ | 
| 114 | 2012-03-01 14:24:02 |       Ȣ | 
| 116 | 2012-03-01 14:24:02 | An extra wide unicode: ҈ | 
| 252 | 2012-03-01 14:24:02 |       ∴ | 
+-----+---------------------+---------------------------+ 

id = 114と116に対応する行は他の行とはあまり一致していないことに注意してください。

(入手可能なパラメータの詳細については、table.tableのdocstringを参照してください。)

+0

良い答え。私はabout \ N {無限}と残りの、そのおかげで分からなかった! –

1

使用mako template HTMLを作成し、そのHTMLを表示するために、任意のテキストベースのブラウザを使用します。

私はそれを使いました。結果をコンソールに適切な形式で表示する必要があります。私は出力を生成するためにunixでlinksを使用しました。 HTMLの表形式を使用して、データを適切な形式で表示できます。

一部のUnicodeは、余分な狭いまたは広いことができるので、私は、任意のUnicodeのための良い解決策を認識していないよあなたがこの

+---------------------------------------+ 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    |---+---+---+---+---+---+---+---+---+---| 
    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 
    +---------------------------------------+ 
+0

良い解決策、私はこの方向ではありませんでした:) しかし、私は外側のlinuxコマンド(リンク)を呼び出さないようにしたいと思います。 Pythonの「出て行く」ことなく同じことをする方法はありますか? – diemacht

2

行うテキストテーブルCheeseshopには少なくとも三つのモジュールがあります:最初の検査最初の2つのオン

  • asciitable
  • texttable
  • PrettyTable

はいないようですが、 Unicodeをそのまま使用することができます(unutbuのサンプルデータはUnicode例外を発生させます)。ただし、PrettyTableは:

import prettytable 
data = [          
    ('id', 'now()', 'aaa'), 
    ('28', '2012-03-01 14:24:02', u'To \N{INFINITY} and beyond'), 
    ('77', '2012-03-01 14:24:02', u"All with me's meet"), 
    ('89', '2012-03-01 14:24:02', u' that I can fashion fit \N{BLACK SMILING FACE}'), 
    ('114', '2012-03-01 14:24:02', u'\N{LATIN CAPITAL LETTER OU}'), 
    ('116', '2012-03-01 14:24:02', u'An extra wide unicode: \N{COMBINING CYRILLIC HUNDRED THOUSANDS SIGN}'), 
    ('252', '2012-03-01 14:24:02', u'\N{THEREFORE}'), 
    ] 
t = prettytable.PrettyTable(['id', 'now()', 'aaa']) 
for row in data: 
    t.add_row(row) 
t.printt() 
+-----+---------------------+---------------------------+ 
| id |  now()  |   aaa   | 
+-----+---------------------+---------------------------+ 
| 28 | 2012-03-01 14:24:02 |  To ∞ and beyond  | 
| 77 | 2012-03-01 14:24:02 |  All with me's meet | 
| 89 | 2012-03-01 14:24:02 | that I can fashion fit ☻ | 
| 114 | 2012-03-01 14:24:02 |    Ȣ    | 
| 116 | 2012-03-01 14:24:02 | An extra wide unicode: ҈ | 
| 252 | 2012-03-01 14:24:02 |    ∴    | 
+-----+---------------------+---------------------------+ 

t.print_html()で出力することもできます。 pip install prettytableをインストールしてください。

関連する問題