最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python和tkinter開發(fā)一個SQLite數(shù)據(jù)庫可視化小工具

 更新時間:2026年03月10日 08:42:52   作者:學習&實踐愛好者  
這篇文章主要為大家詳細介紹了一個基于Python tkinter開發(fā)的SQLite數(shù)據(jù)庫可視化工具,該工具具有簡潔的GUI界面,支持查看數(shù)據(jù)庫表結構、瀏覽數(shù)據(jù)內(nèi)容并能將數(shù)據(jù)導出為CSV文件,感興趣的小伙伴可以了解下

基于 Python tkinter 開發(fā)的SQLite數(shù)據(jù)庫可視化小工具

一個基于 Python tkinter 開發(fā)的桌面 GUI 應用程序,特別適合需要快速查看 SQLite 數(shù)據(jù)庫內(nèi)容的場景——用于可視化查看 SQLite 數(shù)據(jù)庫的結構和數(shù)據(jù),并能將表數(shù)據(jù)導出為CSV文件。

程序采用防御式編程,處理了特殊表名、NULL值等邊界情況,并優(yōu)化了列名獲取方式確保數(shù)據(jù)準確性。該工具適用于需要快速查看和分析SQLite數(shù)據(jù)庫內(nèi)容的開發(fā)場景。

運行界面界面截圖:

運行流程圖:

源碼(參考自網(wǎng)路,進行了適當修改)如下:

# 修復列出的表不全以及表內(nèi)容(列)不完整問題
import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
import sqlite3
import os
from datetime import datetime
 
class SQLiteViewer:
    def __init__(self, root):
        self.root = root
        self.root.title("SQLite可視化工具 V2.01")
        self.root.geometry("1100x750")
        self.root.minsize(800, 600)
         
        # 數(shù)據(jù)庫連接狀態(tài)
        self.db_connection = None
        self.db_path = None
         
        # 初始化UI
        self.setup_ui()
         
    def setup_ui(self):
        """設置界面布局"""
        # 頂部控制面板
        control_frame = ttk.Frame(self.root, padding="10")
        control_frame.pack(fill=tk.X, anchor=tk.W)
         
        # 打開數(shù)據(jù)庫按鈕
        self.open_btn = ttk.Button(control_frame, text="選擇SQLite數(shù)據(jù)庫", command=self.open_database)
        self.open_btn.pack(side=tk.LEFT, padx=5)
         
        # 數(shù)據(jù)庫路徑顯示
        self.db_label = ttk.Label(control_frame, text="未選擇數(shù)據(jù)庫", foreground="gray")
        self.db_label.pack(side=tk.LEFT, padx=10, fill=tk.X, expand=True)
         
        # 導出按鈕(默認禁用)
        self.export_btn = ttk.Button(control_frame, text="導出數(shù)據(jù)", command=self.export_data, state=tk.DISABLED)
        self.export_btn.pack(side=tk.RIGHT, padx=5)
         
        # 中間選擇區(qū)域
        select_frame = ttk.Frame(self.root, padding="10")
        select_frame.pack(fill=tk.X, anchor=tk.W)
         
        ttk.Label(select_frame, text="數(shù)據(jù)表列表:").pack(side=tk.LEFT, padx=5)
         
        # 表選擇下拉框
        self.table_var = tk.StringVar()
        self.table_combobox = ttk.Combobox(select_frame, textvariable=self.table_var, state="readonly", width=30)
        self.table_combobox.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        self.table_combobox.bind("<<ComboboxSelected>>", self.on_table_selected)
         
        # 底部顯示區(qū)域(分為結構和數(shù)據(jù)兩個標簽頁)
        tab_control = ttk.Notebook(self.root)
        tab_control.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
         
        # 表結構標簽頁
        self.structure_tab = ttk.Frame(tab_control)
        tab_control.add(self.structure_tab, text="表結構")
         
        # 數(shù)據(jù)標簽頁
        self.data_tab = ttk.Frame(tab_control)
        tab_control.add(self.data_tab, text="表數(shù)據(jù)")
         
        # 初始化表結構顯示區(qū)域
        self.init_structure_display()
         
        # 初始化數(shù)據(jù)顯示區(qū)域
        self.init_data_display()
         
    def init_structure_display(self):
        """初始化表結構顯示區(qū)域"""
        # 創(chuàng)建滾動文本框顯示表結構
        self.structure_text = scrolledtext.ScrolledText(self.structure_tab, wrap=tk.WORD, font=("Consolas", 10))
        self.structure_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.structure_text.insert(tk.END, "請先選擇數(shù)據(jù)庫文件,然后選擇數(shù)據(jù)表查看結構...")
        self.structure_text.config(state=tk.DISABLED)
         
    def init_data_display(self):
        """初始化數(shù)據(jù)顯示區(qū)域"""
        # 創(chuàng)建表格
        self.data_tree = ttk.Treeview(self.data_tab, show="headings")
        self.data_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
         
        # 添加滾動條
        scrollbar = ttk.Scrollbar(self.data_tab, orient=tk.VERTICAL, command=self.data_tree.yview)
        self.data_tree.configure(yscrollcommand=scrollbar.set)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, padx=(0,5), pady=5)
         
        # 初始提示
        self.data_tree["columns"] = ("tip",)
        self.data_tree.heading("tip", text="提示信息")
        self.data_tree.insert("", tk.END, values=("請先選擇數(shù)據(jù)庫文件和數(shù)據(jù)表查看數(shù)據(jù)...",))
         
    def open_database(self):
        """打開SQLite數(shù)據(jù)庫文件"""
        file_path = filedialog.askopenfilename(
            title="選擇SQLite數(shù)據(jù)庫文件",
            filetypes=[("SQLite Files", "*.db *.sqlite *.sqlite3"), ("All Files", "*.*")]
        )
         
        if not file_path:
            return
         
        try:
            # 關閉之前的連接
            if self.db_connection:
                self.db_connection.close()
             
            # 建立新連接
            self.db_connection = sqlite3.connect(file_path)
            self.db_path = file_path
             
            # 更新界面顯示
            self.db_label.config(text=f"當前數(shù)據(jù)庫:{os.path.basename(file_path)}", foreground="black")
            self.export_btn.config(state=tk.NORMAL)
             
            # 獲取所有表名并更新下拉框
            tables = self.get_all_tables()
            self.table_combobox["values"] = tables
             
            # 清空之前的顯示
            self.clear_structure_display()
            self.clear_data_display()
             
            if tables:
                messagebox.showinfo("成功", f"成功連接數(shù)據(jù)庫!共發(fā)現(xiàn) {len(tables)} 個數(shù)據(jù)表")
            else:
                messagebox.showwarning("警告", "數(shù)據(jù)庫連接成功,但未發(fā)現(xiàn)任何數(shù)據(jù)表")
                 
        except sqlite3.Error as e:
            messagebox.showerror("錯誤", f"數(shù)據(jù)庫連接失敗:{str(e)}")
            self.db_connection = None
            self.db_path = None
            self.db_label.config(text="連接失敗", foreground="red")
            self.export_btn.config(state=tk.DISABLED)
     
    def get_all_tables(self):
        """獲取數(shù)據(jù)庫中所有表名和視圖名"""
        if not self.db_connection:
            return []
         
        cursor = self.db_connection.cursor()
        try:
            # 兼容性最好、最穩(wěn)妥的查詢方式:同時獲取表和視圖
            cursor.execute("""
                SELECT name FROM sqlite_master 
                WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%'
                ORDER BY name
            """)
            tables = [row[0] for row in cursor.fetchall()]
        except sqlite3.Error as e:
            print(f"獲取表列表失敗: {e}")
            tables = []
        finally:
            cursor.close()
            
        return tables

     
    def on_table_selected(self, event):
        """當選擇不同表時的處理"""
        selected_table = self.table_var.get()
        if not selected_table or not self.db_connection:
            return
         
        # 顯示表結構
        self.show_table_structure(selected_table)
         
        # 顯示表數(shù)據(jù)
        self.show_table_data(selected_table)
     
    def show_table_structure(self, table_name):
        """顯示表結構信息"""
        cursor = self.db_connection.cursor()
         
        # 核心防錯:必須處理表名中的雙引號并用雙引號包裹,否則"Order Details"這種帶空格的表會報錯
        safe_table = table_name.replace('"', '""')
         
        # 獲取表結構
        cursor.execute(f'PRAGMA table_info("{safe_table}")')
        structure = cursor.fetchall()
         
        # 獲取表的創(chuàng)建語句 (使用 ? 占位符最安全)
        cursor.execute("""
            SELECT sql FROM sqlite_master 
            WHERE name=? AND type IN ('table', 'view')
        """, (table_name,))
        create_sql = cursor.fetchone()
        create_sql = create_sql[0] if create_sql and create_sql[0] else "未找到創(chuàng)建語句(可能是視圖或系統(tǒng)表)"
         
        cursor.close()
         
        # 更新顯示
        self.clear_structure_display()
        self.structure_text.config(state=tk.NORMAL)
         
        # 寫入表基本信息
        self.structure_text.insert(tk.END, f"=== 結構:{table_name} ===\n\n")
        self.structure_text.insert(tk.END, f"創(chuàng)建語句:\n{create_sql}\n\n")
        self.structure_text.insert(tk.END, "字段信息:\n")
        self.structure_text.insert(tk.END, f"{'序號':<5} {'字段名':<20} {'類型':<15} {'是否主鍵':<10} {'是否允許空':<10} {'默認值':<15}\n")
        self.structure_text.insert(tk.END, "-" * 80 + "\n")
         
        for field in structure:
            cid, name, type_, notnull, dflt_value, pk = field
            is_pk = "是" if pk else "否"
            is_nullable = "否" if notnull else "是"
            default = dflt_value if dflt_value is not None else "無"
             
            self.structure_text.insert(tk.END, f"{cid:<5} {name:<20} {type_:<15} {is_pk:<10} {is_nullable:<10} {default:<15}\n")
         
        self.structure_text.config(state=tk.DISABLED)

     
    def show_table_data(self, table_name):
        """顯示表數(shù)據(jù)"""
        cursor = self.db_connection.cursor()
        safe_table = table_name.replace('"', '""')
         
        try:
            # 獲取所有數(shù)據(jù) (使用安全表名包裹)
            cursor.execute(f'SELECT * FROM "{safe_table}"')
            data = cursor.fetchall()
             
            # 【核心修復】必須使用 cursor.description 獲取實際的列名,
            # 絕對不要用 PRAGMA 去匹配,以防止列數(shù)量錯位或視圖引發(fā)錯誤
            if cursor.description:
                columns = [desc[0] for desc in cursor.description]
            else:
                columns = []
             
            cursor.close()
             
            # 清空之前的數(shù)據(jù)
            self.clear_data_display()
             
            # 設置表格列
            if columns:
                self.data_tree["columns"] = columns
                for col in columns:
                    self.data_tree.heading(col, text=col)
                    self.data_tree.column(col, width=120, anchor=tk.CENTER)
            else:
                # 極端情況:表存在但連列名都沒有定義
                self.data_tree["columns"] = ("tip",)
                self.data_tree.heading("tip", text="提示")
             
            # 插入數(shù)據(jù)
            if data:
                for i, row in enumerate(data):
                    # 處理None值
                    formatted_row = [str(val) if val is not None else "NULL" for val in row]
                    self.data_tree.insert("", tk.END, iid=i, values=formatted_row)
            else:
                # 沒有數(shù)據(jù)時顯示提示
                col_tuple = ("該表暫無數(shù)據(jù)",) + ("",) * (len(columns) - 1) if columns else ("該表沒有定義列",)
                self.data_tree.insert("", tk.END, values=col_tuple)
                 
        except sqlite3.Error as e:
            self.clear_data_display()
            self.data_tree["columns"] = ("error",)
            self.data_tree.heading("error", text="錯誤信息")
            self.data_tree.column("error", anchor=tk.W)
            self.data_tree.insert("", tk.END, values=(f"查詢失敗:{str(e)}",))

     
    def clear_structure_display(self):
        """清空表結構顯示"""
        self.structure_text.config(state=tk.NORMAL)
        self.structure_text.delete(1.0, tk.END)
        self.structure_text.config(state=tk.DISABLED)
     
    def clear_data_display(self):
        """清空數(shù)據(jù)表格"""
        # 刪除所有列
        for col in self.data_tree["columns"]:
            self.data_tree.heading(col, text="")
        self.data_tree["columns"] = ()
         
        # 刪除所有行
        for item in self.data_tree.get_children():
            self.data_tree.delete(item)
     
    def export_data(self):
        """導出當前表的數(shù)據(jù)"""
        selected_table = self.table_var.get()
        if not selected_table or not self.db_connection:
            messagebox.showwarning("警告", "請先選擇數(shù)據(jù)庫和數(shù)據(jù)表")
            return
         
        # 選擇保存路徑
        file_path = filedialog.asksaveasfilename(
            title="導出數(shù)據(jù)",
            defaultextension=".csv",
            filetypes=[("CSV文件", "*.csv"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
         
        if not file_path:
            return
         
        cursor = self.db_connection.cursor()
        safe_table = selected_table.replace('"', '""')
         
        try:
            # 統(tǒng)一修改使用游標去獲取列名確保絕對匹配
            cursor.execute(f'SELECT * FROM "{safe_table}"')
            data = cursor.fetchall()
            columns = [desc[0] for desc in cursor.description] if cursor.description else []
             
            cursor.close()
             
            # 寫入文件
            with open(file_path, "w", encoding="utf-8-sig", newline="") as f:
                # 寫入表頭
                if columns:
                    f.write(",".join(columns) + "\n")
                 
                # 寫入數(shù)據(jù)
                if data:
                    for row in data:
                        formatted_row = []
                        for val in row:
                            if val is None:
                                formatted_val = "NULL"
                            elif isinstance(val, str):
                                if "," in val or "\n" in val or '"' in val:
                                    formatted_val = '"' + val.replace('"', '""') + '"'
                                else:
                                    formatted_val = val
                            else:
                                formatted_val = str(val)
                            formatted_row.append(formatted_val)
                         
                        f.write(",".join(formatted_row) + "\n")
             
            messagebox.showinfo("成功", f"數(shù)據(jù)已成功導出到:\n{file_path}")
             
        except Exception as e:
            messagebox.showerror("錯誤", f"導出數(shù)據(jù)失?。簕str(e)}")

     
    def __del__(self):
        """程序退出時關閉數(shù)據(jù)庫連接"""
        if self.db_connection:
            self.db_connection.close()
 
if __name__ == "__main__":
    root = tk.Tk()
    app = SQLiteViewer(root)
    root.mainloop()

到此這篇關于基于Python和tkinter開發(fā)一個SQLite數(shù)據(jù)庫可視化小工具的文章就介紹到這了,更多相關Python SQLite數(shù)據(jù)庫可視化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • python 編寫簡單網(wǎng)頁服務器的實例

    python 編寫簡單網(wǎng)頁服務器的實例

    今天小編就為大家分享一篇python 編寫簡單網(wǎng)頁服務器的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Python破解excel進入密碼的過程詳解

    Python破解excel進入密碼的過程詳解

    這篇文章主要為大家介紹了如何利用Python破解excel進入密碼,文中的示例代碼講解詳細,對我們學習Python有一定幫助,感興趣的可以動手試一試
    2022-03-03
  • django 外鍵創(chuàng)建注意事項說明

    django 外鍵創(chuàng)建注意事項說明

    這篇文章主要介紹了django 外鍵創(chuàng)建注意事項說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • django之session與分頁(實例講解)

    django之session與分頁(實例講解)

    下面小編就為大家?guī)硪黄猟jango之session與分頁(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • Python數(shù)據(jù)分析之Matplotlib的常用操作總結

    Python數(shù)據(jù)分析之Matplotlib的常用操作總結

    Matplotlib是Python的繪圖庫,它可與NumPy一起使用,提供了一種有效的MatLab開源替代方案,下面這篇文章主要給大家介紹了關于Python數(shù)據(jù)分析之Matplotlib常用操作的相關資料,需要的朋友可以參考下
    2022-01-01
  • Pycharm2020.1安裝中文語言插件的詳細教程(不需要漢化)

    Pycharm2020.1安裝中文語言插件的詳細教程(不需要漢化)

    這篇文章主要介紹了Pycharm2020.1安裝中文語言插件的詳細教程,不需要漢化,本文給大家分享三種方法,在這小編推薦使用方法二,具體內(nèi)容詳情大家跟隨小編一起看看吧
    2020-08-08
  • Python中一般處理中文的幾種方法

    Python中一般處理中文的幾種方法

    今天小編就為大家分享一篇關于Python中一般處理中文的幾種方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 使用pandas read_table讀取csv文件的方法

    使用pandas read_table讀取csv文件的方法

    今天小編就為大家分享一篇使用pandas read_table讀取csv文件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • Python 實現(xiàn) PPT 轉(zhuǎn) HTML的實現(xiàn)示例

    Python 實現(xiàn) PPT 轉(zhuǎn) HTML的實現(xiàn)示例

    本文介紹了利用Spire.Presentation for Python這一專業(yè)組件,通過編程方式實現(xiàn)演示文稿到 HTML 的精準轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2026-03-03
  • Python實現(xiàn)爆破ZIP文件(支持純數(shù)字,數(shù)字+字母,密碼本)

    Python實現(xiàn)爆破ZIP文件(支持純數(shù)字,數(shù)字+字母,密碼本)

    這篇文章主要為大家分享了如何利用Python實現(xiàn)破解zip文件的密碼,能實現(xiàn)破解純數(shù)字、數(shù)字+字母、密碼本等種類的密碼,需要的可以參考一下
    2022-03-03

最新評論

鱼台县| 常山县| 上栗县| 磴口县| 探索| 宕昌县| 临洮县| 灵川县| 黄冈市| 济南市| 鄂温| 哈巴河县| 桂平市| 南乐县| 若尔盖县| 麻阳| 广宁县| 拜泉县| 阿坝县| 阜平县| 晋中市| 图们市| 青州市| 高淳县| 盖州市| 图们市| 通渭县| 峨眉山市| 阜阳市| 社会| 丰镇市| 桓仁| 邵阳市| 五峰| 平原县| 正镶白旗| 阳曲县| 山东省| 定日县| 田阳县| 盖州市|