python 統計MySQL表信息


一、場景描述

線上有一台MySQL服務器,里面有幾十個數據庫,每個庫有N多表。

現在需要將每個表的信息,統計到excel中,格式如下:

庫名 表名 表說明 建表語句
db1 users 用戶表 CREATE TABLE `users` (...)

 

 

 

二、需求分析

怎么做呢?

1. 手動錄入(太TM苦逼了,那么多表呀...)

2. 使用Python自動錄入(Great)

 

三、獲取相關信息

需要利用的技術點,有2個。一個是pymysql(連接mysql),一個是xlwt(寫入excel)

安裝模塊

pip3 install pymysql xlwt

獲取所有數據庫

請確保有一個賬號,能夠遠程連接MySQL,並且有對應的權限。

我用的是本機的MySQL,目前只有一個數據庫db1

新建文件tj.py,內容如下:

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
print(data_all)
View Code

執行輸出:

(('information_schema',), ('db1',), ('mysql',), ('performance_schema',), ('sys',))

 

結果是一個元組,里面的每一個元素也是元組。使用for循環

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    print(i[0])  # 獲取庫名
View Code

執行輸出:

information_schema
db1
mysql
performance_schema
sys

 

獲取所有的表

要獲取所有的表,必須要切換到對應的數據庫中,使用show tables 才可以獲取。

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    conn.select_db(i[0])  # 切換到指定的庫中
    cur.execute('SHOW TABLES')  # 查看庫中所有的表
    ret = cur.fetchall()  # 獲取執行結果
    print(ret)
View Code

執行輸出:

(('CHARACTER_SETS',), ('COLLATIONS',), ('COLLATION_CHARACTER_SET_APPLICABILITY',), ('COLUMNS',), ('COLUMN_PRIVILEGES',), ('ENGINES',), ('EVENTS',), ('FILES',), ('GLOBAL_STATUS',), ('GLOBAL_VARIABLES',), ('KEY_COLUMN_USAGE',), ('OPTIMIZER_TRACE',), ('PARAMETERS',), ('PARTITIONS',), ('PLUGINS',), ('PROCESSLIST',), ('PROFILING',), ('REFERENTIAL_CONSTRAINTS',), ('ROUTINES',), ('SCHEMATA',), ('SCHEMA_PRIVILEGES',), ('SESSION_STATUS',), ('SESSION_VARIABLES',), ('STATISTICS',), ('TABLES',), ('TABLESPACES',), ('TABLE_CONSTRAINTS',), ('TABLE_PRIVILEGES',), ('TRIGGERS',), ('USER_PRIVILEGES',), ('VIEWS',), ('INNODB_LOCKS',), ('INNODB_TRX',), ('INNODB_SYS_DATAFILES',), ('INNODB_FT_CONFIG',), ('INNODB_SYS_VIRTUAL',), ('INNODB_CMP',), ('INNODB_FT_BEING_DELETED',), ('INNODB_CMP_RESET',), ('INNODB_CMP_PER_INDEX',), ('INNODB_CMPMEM_RESET',), ('INNODB_FT_DELETED',), ('INNODB_BUFFER_PAGE_LRU',), ('INNODB_LOCK_WAITS',), ('INNODB_TEMP_TABLE_INFO',), ('INNODB_SYS_INDEXES',), ('INNODB_SYS_TABLES',), ('INNODB_SYS_FIELDS',), ('INNODB_CMP_PER_INDEX_RESET',), ('INNODB_BUFFER_PAGE',), ('INNODB_FT_DEFAULT_STOPWORD',), ('INNODB_FT_INDEX_TABLE',), ('INNODB_FT_INDEX_CACHE',), ('INNODB_SYS_TABLESPACES',), ('INNODB_METRICS',), ('INNODB_SYS_FOREIGN_COLS',), ('INNODB_CMPMEM',), ('INNODB_BUFFER_POOL_STATS',), ('INNODB_SYS_COLUMNS',), ('INNODB_SYS_FOREIGN',), ('INNODB_SYS_TABLESTATS',))
(('school',), ('users',))
(('columns_priv',), ('db',), ('engine_cost',), ('event',), ('func',), ('general_log',), ('gtid_executed',), ('help_category',), ('help_keyword',), ('help_relation',), ('help_topic',), ('innodb_index_stats',), ('innodb_table_stats',), ('ndb_binlog_index',), ('plugin',), ('proc',), ('procs_priv',), ('proxies_priv',), ('server_cost',), ('servers',), ('slave_master_info',), ('slave_relay_log_info',), ('slave_worker_info',), ('slow_log',), ('tables_priv',), ('time_zone',), ('time_zone_leap_second',), ('time_zone_name',), ('time_zone_transition',), ('time_zone_transition_type',), ('user',))
(('accounts',), ('cond_instances',), ('events_stages_current',), ('events_stages_history',), ('events_stages_history_long',), ('events_stages_summary_by_account_by_event_name',), ('events_stages_summary_by_host_by_event_name',), ('events_stages_summary_by_thread_by_event_name',), ('events_stages_summary_by_user_by_event_name',), ('events_stages_summary_global_by_event_name',), ('events_statements_current',), ('events_statements_history',), ('events_statements_history_long',), ('events_statements_summary_by_account_by_event_name',), ('events_statements_summary_by_digest',), ('events_statements_summary_by_host_by_event_name',), ('events_statements_summary_by_program',), ('events_statements_summary_by_thread_by_event_name',), ('events_statements_summary_by_user_by_event_name',), ('events_statements_summary_global_by_event_name',), ('events_transactions_current',), ('events_transactions_history',), ('events_transactions_history_long',), ('events_transactions_summary_by_account_by_event_name',), ('events_transactions_summary_by_host_by_event_name',), ('events_transactions_summary_by_thread_by_event_name',), ('events_transactions_summary_by_user_by_event_name',), ('events_transactions_summary_global_by_event_name',), ('events_waits_current',), ('events_waits_history',), ('events_waits_history_long',), ('events_waits_summary_by_account_by_event_name',), ('events_waits_summary_by_host_by_event_name',), ('events_waits_summary_by_instance',), ('events_waits_summary_by_thread_by_event_name',), ('events_waits_summary_by_user_by_event_name',), ('events_waits_summary_global_by_event_name',), ('file_instances',), ('file_summary_by_event_name',), ('file_summary_by_instance',), ('global_status',), ('global_variables',), ('host_cache',), ('hosts',), ('memory_summary_by_account_by_event_name',), ('memory_summary_by_host_by_event_name',), ('memory_summary_by_thread_by_event_name',), ('memory_summary_by_user_by_event_name',), ('memory_summary_global_by_event_name',), ('metadata_locks',), ('mutex_instances',), ('objects_summary_global_by_type',), ('performance_timers',), ('prepared_statements_instances',), ('replication_applier_configuration',), ('replication_applier_status',), ('replication_applier_status_by_coordinator',), ('replication_applier_status_by_worker',), ('replication_connection_configuration',), ('replication_connection_status',), ('replication_group_member_stats',), ('replication_group_members',), ('rwlock_instances',), ('session_account_connect_attrs',), ('session_connect_attrs',), ('session_status',), ('session_variables',), ('setup_actors',), ('setup_consumers',), ('setup_instruments',), ('setup_objects',), ('setup_timers',), ('socket_instances',), ('socket_summary_by_event_name',), ('socket_summary_by_instance',), ('status_by_account',), ('status_by_host',), ('status_by_thread',), ('status_by_user',), ('table_handles',), ('table_io_waits_summary_by_index_usage',), ('table_io_waits_summary_by_table',), ('table_lock_waits_summary_by_table',), ('threads',), ('user_variables_by_thread',), ('users',), ('variables_by_thread',))
(('host_summary',), ('host_summary_by_file_io',), ('host_summary_by_file_io_type',), ('host_summary_by_stages',), ('host_summary_by_statement_latency',), ('host_summary_by_statement_type',), ('innodb_buffer_stats_by_schema',), ('innodb_buffer_stats_by_table',), ('innodb_lock_waits',), ('io_by_thread_by_latency',), ('io_global_by_file_by_bytes',), ('io_global_by_file_by_latency',), ('io_global_by_wait_by_bytes',), ('io_global_by_wait_by_latency',), ('latest_file_io',), ('memory_by_host_by_current_bytes',), ('memory_by_thread_by_current_bytes',), ('memory_by_user_by_current_bytes',), ('memory_global_by_current_bytes',), ('memory_global_total',), ('metrics',), ('processlist',), ('ps_check_lost_instrumentation',), ('schema_auto_increment_columns',), ('schema_index_statistics',), ('schema_object_overview',), ('schema_redundant_indexes',), ('schema_table_lock_waits',), ('schema_table_statistics',), ('schema_table_statistics_with_buffer',), ('schema_tables_with_full_table_scans',), ('schema_unused_indexes',), ('session',), ('session_ssl_status',), ('statement_analysis',), ('statements_with_errors_or_warnings',), ('statements_with_full_table_scans',), ('statements_with_runtimes_in_95th_percentile',), ('statements_with_sorting',), ('statements_with_temp_tables',), ('sys_config',), ('user_summary',), ('user_summary_by_file_io',), ('user_summary_by_file_io_type',), ('user_summary_by_stages',), ('user_summary_by_statement_latency',), ('user_summary_by_statement_type',), ('version',), ('wait_classes_global_by_avg_latency',), ('wait_classes_global_by_latency',), ('waits_by_host_by_latency',), ('waits_by_user_by_latency',), ('waits_global_by_latency',), ('x$host_summary',), ('x$host_summary_by_file_io',), ('x$host_summary_by_file_io_type',), ('x$host_summary_by_stages',), ('x$host_summary_by_statement_latency',), ('x$host_summary_by_statement_type',), ('x$innodb_buffer_stats_by_schema',), ('x$innodb_buffer_stats_by_table',), ('x$innodb_lock_waits',), ('x$io_by_thread_by_latency',), ('x$io_global_by_file_by_bytes',), ('x$io_global_by_file_by_latency',), ('x$io_global_by_wait_by_bytes',), ('x$io_global_by_wait_by_latency',), ('x$latest_file_io',), ('x$memory_by_host_by_current_bytes',), ('x$memory_by_thread_by_current_bytes',), ('x$memory_by_user_by_current_bytes',), ('x$memory_global_by_current_bytes',), ('x$memory_global_total',), ('x$processlist',), ('x$ps_digest_95th_percentile_by_avg_us',), ('x$ps_digest_avg_latency_distribution',), ('x$ps_schema_table_statistics_io',), ('x$schema_flattened_keys',), ('x$schema_index_statistics',), ('x$schema_table_lock_waits',), ('x$schema_table_statistics',), ('x$schema_table_statistics_with_buffer',), ('x$schema_tables_with_full_table_scans',), ('x$session',), ('x$statement_analysis',), ('x$statements_with_errors_or_warnings',), ('x$statements_with_full_table_scans',), ('x$statements_with_runtimes_in_95th_percentile',), ('x$statements_with_sorting',), ('x$statements_with_temp_tables',), ('x$user_summary',), ('x$user_summary_by_file_io',), ('x$user_summary_by_file_io_type',), ('x$user_summary_by_stages',), ('x$user_summary_by_statement_latency',), ('x$user_summary_by_statement_type',), ('x$wait_classes_global_by_avg_latency',), ('x$wait_classes_global_by_latency',), ('x$waits_by_host_by_latency',), ('x$waits_by_user_by_latency',), ('x$waits_global_by_latency',))
View Code

 

結果也是一個大的元組,使用for循環,提取表名

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    conn.select_db(i[0])  # 切換到指定的庫中
    cur.execute('SHOW TABLES')  # 查看庫中所有的表
    ret = cur.fetchall()  # 獲取執行結果

    for j in ret:
        print(j[0])  # 獲取每一個表名
View Code

執行輸出:

CHARACTER_SETS
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
...
View Code

 

獲取建表語句

使用命令 show create table 表名 獲取

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    conn.select_db(i[0])  # 切換到指定的庫中
    cur.execute('SHOW TABLES')  # 查看庫中所有的表
    ret = cur.fetchall()  # 獲取執行結果

    for j in ret:
        # 獲取每一個表的建表語句
        cur.execute('show create table `%s`;' % j[0])
        ret = cur.fetchall()
        print(ret)
View Code

執行輸出:

(('CHARACTER_SETS', "CREATE TEMPORARY TABLE `CHARACTER_SETS` (\n  `CHARACTER_SET_NAME` varchar(32) NOT NULL DEFAULT '',\n  `DEFAULT_COLLATE_NAME` varchar(32) NOT NULL DEFAULT '',\n  `DESCRIPTION` varchar(60) NOT NULL DEFAULT '',\n  `MAXLEN` bigint(3) NOT NULL DEFAULT '0'\n) ENGINE=MEMORY DEFAULT CHARSET=utf8"),)
...
View Code

 

從結果中可以看出,建表語句中有大量的 \n  這個是換行符。注意:是\n后面還有2個空格

領導肯定是不想看到有這種符號存在,怎么去除呢?使用eval+replace

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    conn.select_db(i[0])  # 切換到指定的庫中
    cur.execute('SHOW TABLES')  # 查看庫中所有的表
    ret = cur.fetchall()  # 獲取執行結果

    for j in ret:
        # 獲取每一個表的建表語句
        cur.execute('show create table `%s`;' % j[0])
        ret = cur.fetchall()
        # print(ret)
        for k in ret:
            # 替換反斜杠,使用\\。替換換行符\n,使用下面的
            structure = eval(repr(k[1]).replace('\\n  ', ''))
            print(structure)
View Code

執行輸出:

CREATE TEMPORARY TABLE `CHARACTER_SETS` (`CHARACTER_SET_NAME` varchar(32) NOT NULL DEFAULT '',`DEFAULT_COLLATE_NAME` varchar(32) NOT NULL DEFAULT '',`DESCRIPTION` varchar(60) NOT NULL DEFAULT '',`MAXLEN` bigint(3) NOT NULL DEFAULT '0'
) ENGINE=MEMORY DEFAULT CHARSET=utf8
...
View Code

發現結果正常了!

 

結果真的很多,但我都需要嗎?no no no,其實我只需要db1而已,其他的都是系統自帶的表,我並不關心!

排除多余的表

定義一個排序列表,使用if排除,注意:i[0] 是庫名

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    # 排序列表,排除mysql自帶的數據庫
    exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
    if i[0] not in exclude_list:  # 判斷不在列表中時
        conn.select_db(i[0])  # 切換到指定的庫中
        cur.execute('SHOW TABLES')  # 查看庫中所有的表
        ret = cur.fetchall()  # 獲取執行結果

        for j in ret:
            # 獲取每一個表的建表語句
            cur.execute('show create table `%s`;' % j[0])
            ret = cur.fetchall()
            # print(ret)
            for k in ret:
                # 替換反斜杠,使用\\。替換換行符\n,使用下面的
                structure = eval(repr(k[1]).replace('\\n  ', ''))
                print(structure)
View Code

執行輸出:

CREATE TABLE `school` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用戶表'
View Code

 

獲取表說明

看下面一條建表語句

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',
  PRIMARY KEY (`id`),
  KEY `ix_users_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用戶表';

我需要獲取 用戶表 這3個字,如何操作?

1. 使用正則匹配?Oh, I'm sorry ,本人正則水平太爛了...

2. 使用COMMENT切割?那可不行,name字段也有COMMENT。

仔細發現,可以看出這2個COMMENT還是有區別的。最后一個COMMENT,后面有一個等號。

OK,那么就可以通過COMMENT=來切割了。

 

 

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    # 排序列表,排除mysql自帶的數據庫
    exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
    if i[0] not in exclude_list:  # 判斷不在列表中時
        conn.select_db(i[0])  # 切換到指定的庫中
        cur.execute('SHOW TABLES')  # 查看庫中所有的表
        ret = cur.fetchall()  # 獲取執行結果

        for j in ret:
            # 獲取每一個表的建表語句
            cur.execute('show create table `%s`;' % j[0])
            ret = cur.fetchall()
            # print(ret)
            for k in ret:
                # 替換反斜杠,使用\\。替換換行符\n,使用下面的
                structure = eval(repr(k[1]).replace('\\n  ', ''))
                # 使用COMMENT= 切割
                res = structure.split("COMMENT=")
                print(res)
View Code

執行輸出:

['CREATE TABLE `school` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci']
["CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ", "'用戶表'"]
View Code

 

注意: 有些表,是沒有寫表注釋的,所以獲取表說明時,要加一個判斷

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    # 排序列表,排除mysql自帶的數據庫
    exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
    if i[0] not in exclude_list:  # 判斷不在列表中時
        conn.select_db(i[0])  # 切換到指定的庫中
        cur.execute('SHOW TABLES')  # 查看庫中所有的表
        ret = cur.fetchall()  # 獲取執行結果

        for j in ret:
            # 獲取每一個表的建表語句
            cur.execute('show create table `%s`;' % j[0])
            ret = cur.fetchall()
            # print(ret)
            for k in ret:
                # 替換反斜杠,使用\\。替換換行符\n,使用下面的
                structure = eval(repr(k[1]).replace('\\n  ', ''))
                # 使用COMMENT= 切割,獲取表說明
                res = structure.split("COMMENT=")

                if len(res) > 1:  # 判斷有表說明的情況下
                    explain = res[1]  # 表說明
                    print(explain)
View Code

執行輸出:

'用戶表'

 

輸出結果是帶有引號的,要去除引號,怎么操作?

使用strip就可以了

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

for i in data_all:
    # 排序列表,排除mysql自帶的數據庫
    exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
    if i[0] not in exclude_list:  # 判斷不在列表中時
        conn.select_db(i[0])  # 切換到指定的庫中
        cur.execute('SHOW TABLES')  # 查看庫中所有的表
        ret = cur.fetchall()  # 獲取執行結果

        for j in ret:
            # 獲取每一個表的建表語句
            cur.execute('show create table `%s`;' % j[0])
            ret = cur.fetchall()
            # print(ret)
            for k in ret:
                # 替換反斜杠,使用\\。替換換行符\n,使用下面的
                structure = eval(repr(k[1]).replace('\\n  ', ''))
                # 使用COMMENT= 切割
                res = structure.split("COMMENT=")

                if len(res) > 1:
                    explain = res[1]  # 表說明
                    # print(explain)
                    explain_new = explain.strip("'")  # 去掉引號
                    print(explain_new)
View Code

執行輸出:

用戶表

 

接下來就需要將數據寫入到excel中,但是,我們需要知道。寫入excel,要不斷的調整方位。

由於線上表眾多,獲取一次數據,需要幾分鍾時間,時間上耗費不起!

所以為了避免這種問題,需要將獲取到的數據,寫入json文件中。

構造json數據

既然要構造json數據,那么數據格式,要規划好才行!我構造的數據格式如下:

dic = {
    "庫名":{
        'name': "庫名", 'table_list': [
            {'tname':"表名",'structure':"建表語句",'explain':"表說明"}
        ]
    }
}

從上面可以看出,這是一個三層的數據嵌套

 

定義一個大字典,寫入數據

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

dic = {}  # 大字典,第一層
for i in data_all:
    if i[0] not in dic:  # 判斷庫名不在dic中時
        # 排序列表,排除mysql自帶的數據庫
        exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
        if i[0] not in exclude_list:  # 判斷不在列表中時
            # 寫入第二層數據
            dic[i[0]] = {'name': i[0], 'table_list': []}
            conn.select_db(i[0])  # 切換到指定的庫中
            cur.execute('SHOW TABLES')  # 查看庫中所有的表
            ret = cur.fetchall()  # 獲取執行結果

            for j in ret:
                # 獲取每一個表的建表語句
                cur.execute('show create table `%s`;' % j[0])
                ret = cur.fetchall()
                # print(ret)
                for k in ret:
                    # 替換反斜杠,使用\\。替換換行符\n,使用下面的
                    structure = eval(repr(k[1]).replace('\\n  ', ''))
                    # 使用COMMENT= 切割
                    res = structure.split("COMMENT=")

                    if len(res) > 1:
                        explain = res[1]  # 表說明
                        # print(explain)
                        explain_new = explain.strip("'")  # 去掉引號
                        # 寫入第三層數據,分別是表名,建表語句,表說明
                        dic[i[0]]['table_list'].append({'tname': k[0], 'structure': structure,'explain':explain_new})

print(dic)
View Code

執行輸出:

{'db1': {'name': 'db1', 'table_list': [{'tname': 'users', 'structure': "CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用戶表'", 'explain': '用戶表'}]}}

 

寫入json文件

import pymysql
import json

conn = pymysql.connect(
    host="127.0.0.1",  # mysql ip地址
    user="root",
    passwd="",
    port=3306  # mysql 端口號,注意:必須是int類型
)

cur = conn.cursor()  # 創建游標

# 獲取mysql中所有數據庫
cur.execute('SHOW DATABASES')

data_all = cur.fetchall()  # 獲取執行的返回結果
# print(data_all)

dic = {}  # 大字典,第一層
for i in data_all:
    if i[0] not in dic:  # 判斷庫名不在dic中時
        # 排序列表,排除mysql自帶的數據庫
        exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
        if i[0] not in exclude_list:  # 判斷不在列表中時
            # 寫入第二層數據
            dic[i[0]] = {'name': i[0], 'table_list': []}
            conn.select_db(i[0])  # 切換到指定的庫中
            cur.execute('SHOW TABLES')  # 查看庫中所有的表
            ret = cur.fetchall()  # 獲取執行結果

            for j in ret:
                # 獲取每一個表的建表語句
                cur.execute('show create table `%s`;' % j[0])
                ret = cur.fetchall()
                # print(ret)
                for k in ret:
                    # 替換反斜杠,使用\\。替換換行符\n,使用下面的
                    structure = eval(repr(k[1]).replace('\\n  ', ''))
                    # 使用COMMENT= 切割
                    res = structure.split("COMMENT=")

                    if len(res) >= 1:
                        if len(res) == 1:
                            explain = ""
                        else:
                            explain = res[1]  # 表說明
                        # print(explain)
                        explain_new = explain.strip("'")  # 去掉引號
                        # 寫入第三層數據,分別是表名,建表語句,表說明
                        dic[i[0]]['table_list'].append({'tname': k[0], 'structure': structure,'explain':explain_new})

# print(dic)
with open('tj.json','w',encoding='utf-8') as f:
    f.write(json.dumps(dic))
View Code

 

執行程序,查看tj.json文件內容

{"db1": {"name": "db1", "table_list": [{"tname": "users", "structure": "CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '\u59d3\u540d',PRIMARY KEY (`id`),KEY `ix_users_name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='\u7528\u6237\u8868'", "explain": "\u7528\u6237\u8868"}]}}

 

四、寫入excel中

坐標體系

a1單元格的坐標為0,0。在xlrd模塊里面,坐標都是數字,所以不能用a1表示。

坐標如下:

 

先來寫入一段示例數據

新建文件excel.py,代碼如下:

import xlwt
f = xlwt.Workbook()
sheet1 = f.add_sheet('學生',cell_overwrite_ok=True)
row0 = ["姓名","年齡","出生日期","愛好"]
colum0 = ["張三","李四","王五"]
#寫第一行
for i in range(0,len(row0)):
    sheet1.write(0,i,row0[i])

#寫第一列
for i in range(0,len(colum0)):
    sheet1.write(i+1,0,colum0[i])

# 寫入一行數據
sheet1.write(1,1,"23")
sheet1.write(1,2,"1990")
sheet1.write(1,3,"")

f.save('test.xls')
View Code

執行程序,查看excel文件內容

 

正式寫入excel中

寫入庫名

熟悉語法之后,就可以寫入到excel中了

編輯 excel.py,代碼如下:

import xlwt
import json
f = xlwt.Workbook()
sheet1 = f.add_sheet('統計', cell_overwrite_ok=True)
row0 = ["庫名", "表名", "表說明", "建表語句"]

# 寫第一行
for i in range(0, len(row0)):
    sheet1.write(0, i, row0[i])

# 加載json文件
with open("tj.json", 'r') as load_f:
    load_dict = json.load(load_f)  # 反序列化文件

    num = 0  # 計數器
    for i in load_dict:
        # 寫入庫名
        sheet1.write(num + 1, 0, i)

    f.save('test1.xls')
View Code

執行程序,查看excel文件

 

寫入表名

import xlwt
import json
f = xlwt.Workbook()
sheet1 = f.add_sheet('統計', cell_overwrite_ok=True)
row0 = ["庫名", "表名", "表說明", "建表語句"]

# 寫第一行
for i in range(0, len(row0)):
    sheet1.write(0, i, row0[i])

# 加載json文件
with open("tj.json", 'r') as load_f:
    load_dict = json.load(load_f)  # 反序列化文件

    num = 0  # 計數器
    for i in load_dict:
        # 寫入庫名
        sheet1.write(num + 1, 0, i)
        # 遍歷所有表
        for j in load_dict[i]["table_list"]:
            # 寫入表名
            sheet1.write(num + 1, 1, j['tname'])

    f.save('test1.xls')
View Code

執行程序,查看excel文件

 

寫入表說明和建表語句

import xlwt
import json
f = xlwt.Workbook()
sheet1 = f.add_sheet('統計', cell_overwrite_ok=True)
row0 = ["庫名", "表名", "表說明", "建表語句"]

# 寫第一行
for i in range(0, len(row0)):
    sheet1.write(0, i, row0[i])

# 加載json文件
with open("tj.json", 'r') as load_f:
    load_dict = json.load(load_f)  # 反序列化文件

    num = 0  # 計數器
    for i in load_dict:
        # 寫入庫名
        sheet1.write(num + 1, 0, i)
        # 遍歷所有表
        for j in load_dict[i]["table_list"]:
            # 寫入表名
            sheet1.write(num + 1, 1, j['tname'])
            # 寫入表說明
            sheet1.write(num + 1, 2, j['explain'])
            # 寫入建表語句
            sheet1.write(num + 1, 3, j['structure'])
            num += 1  # 自增1

    f.save('test1.xls')
View Code

注意:默認的num必須要自增,否則多個數據庫寫入會有問題

 

執行程序,查看excel文件

 

總結:

案例只是寫入一個數據庫,那么多個數據庫,也是同樣的代碼。

 

有序字典

假設說,excel的內容是這樣的

我需要對庫名做一個排序,將abc和adb放在前2行,第三行是db1。該如何操作呢?

對於python 3.6之前,默認的字典都是無序的。如果需要將普通字典轉換為有序字典,需要使用OrderedDict

 

舉例:

from collections import OrderedDict
dic = {"k":1,"a":2,"d":4}
order_dic = OrderedDict()  # 實例化一個有序字典
for i in sorted(dic):  # 必須先對普通字典key做排序
    order_dic[i] = dic[i]  # 寫入有序字典中

print(order_dic)

執行輸出:

OrderedDict([('a', 2), ('d', 4), ('k', 1)])

注意:將普通字典轉換為有序字典時,必須要先對普通字典,做一次排序。那么之后寫入到有序字典之后,順序就是有序了!

不論執行多少次print,結果都是一樣的!

 

改造excel寫入

編輯 excel.py,代碼如下:

import xlwt
import json
from collections import OrderedDict

f = xlwt.Workbook()
sheet1 = f.add_sheet('統計', cell_overwrite_ok=True)
row0 = ["庫名", "表名", "表說明", "建表語句"]

# 寫第一行
for i in range(0, len(row0)):
    sheet1.write(0, i, row0[i])

# 加載json文件
with open("tj.json", 'r') as load_f:
    load_dict = json.load(load_f)  # 反序列化文件
    order_dic = OrderedDict()  # 有序字典
    for key in sorted(load_dict):  # 先對普通字典key做排序
        order_dic[key] = load_dict[key]  # 再寫入key

    num = 0  # 計數器
    for i in order_dic:
        # 寫入庫名
        sheet1.write(num + 1, 0, i)
        # 遍歷所有表
        for j in order_dic[i]["table_list"]:
            # 寫入表名
            sheet1.write(num + 1, 1, j['tname'])
            # 寫入表說明
            sheet1.write(num + 1, 2, j['explain'])
            # 寫入建表語句
            sheet1.write(num + 1, 3, j['structure'])

            num += 1  # 自增1

    f.save('test1.xls')
View Code

執行程序,效果同上(因為數據太少了)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM