Печать результатов в формате MySQL с помощью Python
Каков самый простой способ распечатать результат запроса MySQL так же, как MySQL печатает их в консоли с помощью Python? Например, я хотел бы получить что-то вроде этого:
+---------------------+-----------+---------+
| font | documents | domains |
+---------------------+-----------+---------+
| arial | 99854 | 5741 |
| georgia | 52388 | 1955 |
| verdana | 43219 | 2388 |
| helvetica neue | 22179 | 1019 |
| helvetica | 16753 | 1036 |
| lucida grande | 15431 | 641 |
| tahoma | 10038 | 594 |
| trebuchet ms | 8868 | 417 |
| palatino | 5794 | 177 |
| lucida sans unicode | 3525 | 116 |
| sans-serif | 2947 | 216 |
| times new roman | 2554 | 161 |
| proxima-nova | 2076 | 36 |
| droid sans | 1773 | 78 |
| calibri | 1735 | 64 |
| open sans | 1479 | 60 |
| segoe ui | 1273 | 57 |
+---------------------+-----------+---------+
17 rows in set (19.43 sec)
Примечание. Я не знаю максимальную ширину для каждого столбца априори, и все же я хотел бы иметь возможность, не переходя через таблицу дважды. Должен ли я добавить к длине запроса() для каждого столбца? Как MySQL это делает, чтобы не сильно повлиять на память или время обработки?
ИЗМЕНИТЬ
Я не думал, что это относится к вопросу, но это запрос, который я отправляю:
SELECT font.font as font,count(textfont.textid) as documents, count(DISTINCT td.domain) as domains
FROM textfont
RIGHT JOIN font
ON textfont.fontid = font.fontid
RIGHT JOIN (
SELECT text.text as text,url.domain as domain, text.textid as textid
FROM text
RIGHT JOIN url
ON text.texturl = url.urlid) as td
ON textfont.textid = td.textid
WHERE textfont.fontpriority <= 0
AND textfont.textlen > 100
GROUP BY font.font
HAVING documents >= 1000 AND domains >= 10
ORDER BY 2 DESC;
И это код python, который я использую:
import MySQLdb as mdb
print "%s\t\t\t%s\t\t%s" % ("font","documents","domains")
res = cur.execute(query , (font_priority,text_len,min_texts,min_domains))
for res in cur.fetchall():
print "%s\t\t\t%d\t\t%d" % (res[0],res[1],res[2])
Но этот код создает беспорядочный вывод из-за разной ширины.
Ответы
Ответ 1
Используйте prettytable
x = PrettyTable(["City name", "Area", "Population", "Annual Rainfall"])
x.set_field_align("City name", "l") # Left align city names
x.set_padding_width(1) # One space between column edges and contents (default)
x.add_row(["Adelaide",1295, 1158259, 600.5])
x.add_row(["Brisbane",5905, 1857594, 1146.4])
x.add_row(["Darwin", 112, 120900, 1714.7])
x.add_row(["Hobart", 1357, 205556, 619.5])
x.add_row(["Sydney", 2058, 4336374, 1214.8])
x.add_row(["Melbourne", 1566, 3806092, 646.9])
x.add_row(["Perth", 5386, 1554769, 869.4])
print x
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Sydney | 2058 | 4336374 | 1214.8 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
+-----------+------+------------+-----------------+
Ответ 2
Нет необходимости в внешней библиотеке. Распечатывает данные с именами столбцов. Все строки с переменной столбцов можно исключить, если вам не нужны имена столбцов.
sql = "SELECT * FROM someTable"
cursor.execute(sql)
conn.commit()
results = cursor.fetchall()
widths = []
columns = []
tavnit = '|'
separator = '+'
for cd in cursor.description:
widths.append(max(cd[2], len(cd[0])))
columns.append(cd[0])
for w in widths:
tavnit += " %-"+"%ss |" % (w,)
separator += '-'*w + '--+'
print(separator)
print(tavnit % tuple(columns))
print(separator)
for row in results:
print(tavnit % row)
print(separator)
Это вывод:
+--------+---------+---------------+------------+------------+
| ip_log | user_id | type_id | ip_address | time_stamp |
+--------+---------+---------------+------------+------------+
| 227 | 1 | session_login | 10.0.0.2 | 1358760386 |
| 140 | 1 | session_login | 10.0.0.2 | 1358321825 |
| 98 | 1 | session_login | 10.0.0.2 | 1358157588 |
+--------+---------+---------------+------------+------------+
Магия лежит в третьем столбце каждой строки cursor.description
(называемой cd[2]
в коде). Этот столбец представляет длину в символах самого длинного значения. Таким образом, мы расставляем отображаемый столбец как больше между этим и длиной самого заголовка столбца (max(cd[2], len(cd[0]))
).
Ответ 3
Данные находятся в каком-то списке, и они печатают заголовок. Рассмотрим некоторые форматирования следующим образом:
res = ['trebuchet ms', 8868, 417]
res = ['lucida sans unicode', 3525, 116]
и
print(' {0[0]:20s} {0[1]:10d} {0[2]:10d}'.format(res))
предоставит вам
trebuchet ms 8868 417
lucida sans unicode 3525 116
Обратите внимание, что индексирование в список выполняется внутри строки, format
нужно только указать список или кортеж.
В качестве альтернативы вы можете указать ширину программно:
wid1 = 20
wid2 = 10
wid3 = 10
print(' {:{}s} {:{}d} {:{}d}'.format(res[0], wid1, res[1], wid2, res[2], wid3))
который дает идентичный результат, как указано выше.
Вам нужно будет отрегулировать ширину поля по мере необходимости и прокрутить список для каждой строки данных вместо составленных строк. Номера автоматически правы, строка автоматически остается.
Преимущество для некоторых - это, конечно, то, что это не зависит от каких-либо внешних библиотек и выполняется с тем, что уже предоставляет Python.
Ответ 4
Вам нужно сделать два прохода:
- Вычислить ширину столбца
- Распечатайте таблицу
Итак,
table = cur.fetchall()
widths = [0]*len(table[0]) # Assuming there is always one row
for row in table:
widths = [max(w,len(c)) for w,c in zip(widths,row)]
Теперь вы можете распечатать таблицу тривиально.
Помните метод string.rjust
при печати номеров.
Обновление
Более функциональный способ вычисления widths
:
sizetable = [map(len,row) for row in table]
widths = map(max, zip(*sizetable))
Ответ 5
Лучший и самый простой способ распечатать результаты MySQL в формате MySQL Table с использованием tabulate
Python Library
[email protected]$ pip install tabulate
Код Python:
import mysql.connector
from tabulate import tabulate
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="password",
database="testDB"
)
mycursor = mydb.cursor()
mycursor.execute("SELECT emp_name, salary FROM emp_table")
myresult = mycursor.fetchall()
print(tabulate(myresult, headers=['EmpName', 'EmpSalary'], tablefmt='psql'))
Выход:
[email protected]:~$ python python_mysql.py
+------------+-------------+
| EmpName | EmpSalary |
|------------+-------------|
| Ram | 400 |
| Dipankar | 100 |
| Santhosh | 200 |
| Nirmal | 470 |
| Santu | 340 |
| Shiva | 100 |
| Karthik | 500 |
+------------+-------------+