利用Python绘制ER图

最近做了一个挺有意思的小工具,就是用Python读取数据库,然后绘制出一个ER图,可以体现出来主外键等信息。
主要用到的两个库:pymysql和graphviz
注意,graphviz在anaconda的虚拟环境里是不能直接用conda install指令安装的,需要在官网下载安装包,配置环境变量,然后利用pip install指令安装。
接下来是代码部分:
首先是创建3个类:数据库类、表类和属性类:

class database:
    def __init__(self,name,tables,tables_name,foreign_keys):
        self.name=name
        self.tables=tables
        self.tables_name=tables_name
        self.foreign_keys=foreign_keys

class table:
    def __init__(self,name):
        self.name=name
        self.columns=[]
    def printinf(self):
        strr='表名:'+self.name+':'+'\n'
        for i in range(len(self.columns)):
            strr+=self.columns[i].printinf()+'\n'
        print(strr)
        return strr
class column:
    def __init__(self,data):
        self.name=data[0]
        self.columntype=data[1]
        self.extra=data[2]
    def printinf(self):
        strr=str(self.name)+' '+str(self.columntype)+' '+self.extra
        return strr

定义访问数据库的函数:

def getconnection(username,password,dbname):
    #初始化几个数组存储对象
    tables_name=[]
    tables=[]
    foregin_keys=[]

    #打开数据库连接
    conn = pymysql.connect(user = username,passwd = password,database = dbname)

    #创建游标进行数据库操作
    cursor=conn.cursor()

    #获取所有表名
    sqlstring_gettablename="select table_name from information_schema.tables where table_schema='test_database'"
    cursor.execute(sqlstring_gettablename)
    while 1:
        res=cursor.fetchone()
        if res is None:
            #表示已经取完结果集
            break
        tables_name.append(res[0])
    for i in tables_name:
        temp_table=table(i)
        tables.append(temp_table)

    #获取属性
    for i in range(len(tables)):
        #print(tables[i].name)
        sqlstring_getcolumn='SELECT COLUMN_NAME "字段名称",COLUMN_TYPE "字段类型长度",IF(EXTRA="auto_increment",CONCAT(COLUMN_KEY,"(", IF(EXTRA="auto_increment","自增长",EXTRA),")"),COLUMN_KEY) "主外键" FROM information_schema. COLUMNS WHERE TABLE_SCHEMA = "test_database" AND TABLE_NAME = "'+tables[i].name+'"';
        cursor.execute(sqlstring_getcolumn)
        while 1:
            res=cursor.fetchone()
            if res is None:
                #表示已经取完结果集
                break
            temp_column=column(res)
            tables[i].columns.append(temp_column)

    #获取外键
    for i in range(len(tables)):
        #print(tables[i].name)
        sqlstring_getfk='SELECT C.REFERENCED_TABLE_NAME  父表名称 ,C.TABLE_NAME 子表名称 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE C JOIN INFORMATION_SCHEMA. TABLES T ON T.TABLE_NAME = C.TABLE_NAME JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON R.TABLE_NAME = C.TABLE_NAME AND R.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND R.REFERENCED_TABLE_NAME = C.REFERENCED_TABLE_NAME WHERE C.REFERENCED_TABLE_NAME IS NOT NULL AND  C.REFERENCED_TABLE_NAME="'+tables[i].name+'"'
        cursor.execute(sqlstring_getfk)
        while 1:
            res=cursor.fetchone()
            if res is None:
                #表示已经取完结果集
                break
            foregin_keys.append(res)

    cursor.close()
    conn.close()
    db=database('MyDB',tables,tables_name,foregin_keys)
    return db

接下来就是用graphviz绘制ER图:

def draw_ER(db):
    tables_name=db.tables_name
    tables=db.tables
    foreign_keys=db.foreign_keys
    #创建一个空白图
    dot = gz.Graph()
    for i in range(len(tables)):
        dot.node(str(i+1),tables[i].printinf(),shape='rectangle')
    edges=[]
    for i in range(len(foreign_keys)):
        temp_edge=str(tables_name.index(foreign_keys[i][0])+1)+str(tables_name.index(foreign_keys[i][1])+1)
        edges.append(temp_edge)
        #创建边(表示外键关系)
        dot.edge(str(tables_name.index(foreign_keys[i][0])+1),str(tables_name.index(foreign_keys[i][1])+1))
    dot.view()
    dot.save('before_xml.dot')

最后绘制出来的效果是这样的:
在这里插入图片描述
乱码是中文的“表名”,应该是因为编码问题显示有问题。
这个不如自己用专门的ER图软件走出来精美,但是挺方便的。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要在 Python绘制元素周期表,可以使用 Matplotlib 库。以下是一个简单的示例代码: ```python import matplotlib.pyplot as plt # 定义元素周期表中各元素的位置和名称 elements = { 'H': (1, 1), 'He': (18, 1), 'Li': (1, 2), 'Be': (2, 2), 'B': (13, 2), 'C': (14, 2), 'N': (15, 2), 'O': (16, 2), 'F': (17, 2), 'Ne': (18, 2), 'Na': (1, 3), 'Mg': (2, 3), 'Al': (13, 3), 'Si': (14, 3), 'P': (15, 3), 'S': (16, 3), 'Cl': (17, 3), 'Ar': (18, 3), 'K': (1, 4), 'Ca': (2, 4), 'Sc': (3, 4), 'Ti': (4, 4), 'V': (5, 4), 'Cr': (6, 4), 'Mn': (7, 4), 'Fe': (8, 4), 'Co': (9, 4), 'Ni': (10, 4), 'Cu': (11, 4), 'Zn': (12, 4), 'Ga': (13, 4), 'Ge': (14, 4), 'As': (15, 4), 'Se': (16, 4), 'Br': (17, 4), 'Kr': (18, 4), 'Rb': (1, 5), 'Sr': (2, 5), 'Y': (3, 5), 'Zr': (4, 5), 'Nb': (5, 5), 'Mo': (6, 5), 'Tc': (7, 5), 'Ru': (8, 5), 'Rh': (9, 5), 'Pd': (10, 5), 'Ag': (11, 5), 'Cd': (12, 5), 'In': (13, 5), 'Sn': (14, 5), 'Sb': (15, 5), 'Te': (16, 5), 'I': (17, 5), 'Xe': (18, 5), 'Cs': (1, 6), 'Ba': (2, 6), 'La': (3, 6), 'Ce': (4, 6), 'Pr': (5, 6), 'Nd': (6, 6), 'Pm': (7, 6), 'Sm': (8, 6), 'Eu': (9, 6), 'Gd': (10, 6), 'Tb': (11, 6), 'Dy': (12, 6), 'Ho': (13, 6), 'Er': (14, 6), 'Tm': (15, 6), 'Yb': (16, 6), 'Lu': (17, 6), 'Hf': (4, 7), 'Ta': (5, 7), 'W': (6, 7), 'Re': (7, 7), 'Os': (8, 7), 'Ir': (9, 7), 'Pt': (10, 7), 'Au': (11, 7), 'Hg': (12, 7), 'Tl': (13, 7), 'Pb': (14, 7), 'Bi': (15, 7), 'Th': (3, 8), 'Pa': (4, 8), 'U': (5, 8), 'Np': (6, 8), 'Pu': (7, 8), 'Am': (8, 8), 'Cm': (9, 8), 'Bk': (10, 8), 'Cf': (11, 8), 'Es': (12, 8), 'Fm': (13, 8), 'Md': (14, 8), 'No': (15, 8), 'Lr': (16, 8)} # 绘制周期表的框架 fig, ax = plt.subplots(figsize=(8, 12)) for i in range(1, 19): ax.plot([i, i], [1, 8], color='gray', linewidth=1) for i in range(1, 9): ax.plot([1, 18], [i, i], color='gray', linewidth=1) # 在周期表中添加元素名称 for symbol, (x, y) in elements.items(): ax.text(x, y, symbol, ha='center', va='center', fontsize=12) # 设置坐标轴和标题 ax.set_xlim(0.5, 18.5) ax.set_ylim(0.5, 8.5) ax.set_xticks(list(range(1, 19))) ax.set_yticks(list(range(1, 9))) ax.set_xlabel('Group', fontsize=16) ax.set_ylabel('Period', fontsize=16) ax.set_title('Periodic Table of Elements', fontsize=20, fontweight='bold') plt.show() ``` 这段代码使用了一个字典 `elements` 来存储元素名称和位置信息,然后通过循环在周期表中绘制出各个元素的名称和位置。最后调整坐标轴和标题等绘图参数,就可以生成一个简单的周期表图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值