初始化提交

This commit is contained in:
2025-12-29 22:08:58 +08:00
commit c9259b51c7
9 changed files with 1367 additions and 0 deletions

447
main.py Normal file
View File

@@ -0,0 +1,447 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
多数据库交互脚本
支持 MySQL, MongoDB, Redis, SQLite, PostgreSQL
跨平台支持: Windows, Linux, Termux 等
"""
import sys
import json
# 导入数据库模块(处理可能的导入错误)
try:
from mysql_db import MySQLDatabase
from mongodb_db import MongoDatabase
from redis_db import RedisDatabase
from sqlite_db import SQLiteDatabase
from postgres_db import PostgreSQLDatabase
except ImportError as e:
print(f"错误: 导入数据库模块失败")
print(f"详细信息: {e}")
print("\n请确保已安装所需的依赖包:")
print(" pip install -r requirements.txt")
sys.exit(1)
def print_banner():
"""打印欢迎信息"""
banner = """
╔══════════════════════════════════════════╗
║ 多数据库交互工具 v1.0 ║
║ 支持: MySQL, MongoDB, Redis, ║
║ SQLite, PostgreSQL ║
╚══════════════════════════════════════════╝
"""
print(banner)
def print_help():
"""打印帮助信息"""
help_text = """
========================================================================
脚本通用命令:
- help : 显示帮助信息
- connect : 连接到数据库
- disconnect : 断开数据库连接
- status : 查看连接状态
- switch <db> : 切换数据库类型 (mysql/mongodb/redis/sqlite/postgres)
- show databases: 列出所有数据库 (仅MySQL/PostgreSQL)
- use <database>: 切换到指定数据库 (仅MySQL/PostgreSQL)
- quit/exit : 退出程序
========================================================================
MySQL/PostgreSQL/SQLite 通用SQL语句:
SELECT * FROM users;
INSERT INTO users (name, age) VALUES ('张三', 25);
UPDATE users SET age = 26 WHERE name = '张三';
DELETE FROM users WHERE name = '张三';
========================================================================
SQLite 点命令:
.tables - 列出所有表
.schema - 显示所有表的结构
.schema <table> - 显示特定表的结构
.databases - 列出数据库信息
.indexes - 列出所有索引
.indexes <table> - 列出特定表的索引
========================================================================
MongoDB Shell 命令:
show dbs - 列出所有数据库
show collections - 列出当前数据库的集合
use <database> - 切换数据库
========================================================================
MongoDB JSON 命令:
{"collection": "users", "operation": "find", "query": {}}
{"collection": "users", "operation": "insert", "document": {"name": "张三", "age": 25}}
{"collection": "users", "operation": "update", "query": {"name": "张三"}, "update": {"$set": {"age": 26}}}
{"collection": "users", "operation": "delete", "query": {"name": "张三"}}
========================================================================
Redis 键值命令:
SET name 张三
GET name
HSET user:1 name 张三 age 25
HGETALL user:1
KEYS *
========================================================================
"""
print(help_text)
def get_database_config(db_type):
"""
获取数据库配置
:param db_type: 数据库类型
:return: 配置字典
"""
config = {}
if db_type == 'mysql':
print("\n请输入 MySQL 配置信息:")
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
config['port'] = int(input("端口 [3306]: ").strip() or '3306')
config['user'] = input("用户名 [root]: ").strip() or 'root'
config['password'] = input("密码: ").strip()
# 默认先列出数据库,然后让用户选择
config['database'] = None # 先不指定数据库
config['_list_databases'] = True # 标记需要列出数据库
elif db_type == 'mongodb':
print("\n请输入 MongoDB 配置信息:")
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
config['port'] = int(input("端口 [27017]: ").strip() or '27017')
config['database'] = input("数据库名 [test]: ").strip() or 'test'
# 询问是否需要认证
need_auth = input("是否需要用户认证? (y/n) [n]: ").strip().lower()
if need_auth == 'y':
config['username'] = input("用户名: ").strip()
config['password'] = input("密码: ").strip()
else:
config['username'] = None
config['password'] = None
elif db_type == 'redis':
print("\n请输入 Redis 配置信息:")
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
config['port'] = int(input("端口 [6379]: ").strip() or '6379')
config['db'] = int(input("数据库编号 [0]: ").strip() or '0')
password = input("密码 (留空表示无密码): ").strip()
config['password'] = password if password else None
elif db_type == 'sqlite':
print("\n请输入 SQLite 配置信息:")
config['database'] = input("数据库文件路径 [database.db]: ").strip() or 'database.db'
elif db_type == 'postgres':
print("\n请输入 PostgreSQL 配置信息:")
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
config['port'] = int(input("端口 [5432]: ").strip() or '5432')
config['user'] = input("用户名 [postgres]: ").strip() or 'postgres'
config['password'] = input("密码: ").strip()
# 默认先列出数据库,然后让用户选择
config['database'] = 'postgres' # 先连接到默认数据库
config['_list_databases'] = True # 标记需要列出数据库
return config
def create_database_instance(db_type, config):
"""
创建数据库实例
:param db_type: 数据库类型
:param config: 配置字典
:return: 数据库实例
"""
if db_type == 'mysql':
return MySQLDatabase(**config)
elif db_type == 'mongodb':
return MongoDatabase(**config)
elif db_type == 'redis':
return RedisDatabase(**config)
elif db_type == 'sqlite':
return SQLiteDatabase(**config)
elif db_type == 'postgres':
return PostgreSQLDatabase(**config)
else:
return None
def format_output(data):
"""
格式化输出结果
:param data: 数据
:return: 格式化后的字符串
"""
if isinstance(data, list):
# 检查是否是字符串列表(如 .schema 的输出)
if data and all(isinstance(item, str) for item in data):
# 直接输出,保留换行符
return '\n\n'.join(data)
else:
# JSON 格式化
return json.dumps(data, ensure_ascii=False, indent=2)
elif isinstance(data, dict):
return json.dumps(data, ensure_ascii=False, indent=2)
else:
return str(data)
def main():
"""主函数"""
print_banner()
# 选择数据库类型
print("请选择数据库类型:")
print("1. MySQL")
print("2. MongoDB")
print("3. Redis")
print("4. SQLite")
print("5. PostgreSQL")
choice = input("\n请输入选项 (1-5): ").strip()
db_types = {
'1': 'mysql',
'2': 'mongodb',
'3': 'redis',
'4': 'sqlite',
'5': 'postgres'
}
if choice not in db_types:
print("无效的选项!")
return
current_db_type = db_types[choice]
print(f"\n已选择: {current_db_type.upper()}")
# 获取配置并创建数据库实例
config = get_database_config(current_db_type)
list_databases = config.pop('_list_databases', False)
db = create_database_instance(current_db_type, config)
if not db:
print("创建数据库实例失败!")
return
# 是否自动连接
#auto_connect = input("\n是否立即连接? (y/n) [y]: ").strip().lower()
#if auto_connect != 'n':
success, message = db.connect()
print(f"\n{message}")
connected = success
# 如果需要列出数据库
if connected and list_databases and hasattr(db, 'list_databases'):
success_list, result = db.list_databases()
if success_list:
print("\n可用的数据库:")
for i, db_name in enumerate(result, 1):
print(f" {i}. {db_name}")
# 让用户选择数据库
if current_db_type in ['mysql', 'postgres']:
while True:
db_choice = input("\n请输入数据库名或编号 (直接回车跳过): ").strip()
if not db_choice:
break
# 判断是数字还是数据库名
selected_db = None
if db_choice.isdigit():
index = int(db_choice) - 1
if 0 <= index < len(result):
selected_db = result[index]
else:
print(f"错误: 编号超出范围,请输入 1-{len(result)} 之间的数字")
retry = input("是否重新输入? (y/n) [y]: ").strip().lower()
if retry == 'n':
break
continue
else:
selected_db = db_choice
# 尝试切换数据库
use_success, use_msg = db.use_database(selected_db)
print(use_msg)
if use_success:
break
else:
retry = input("是否重新输入? (y/n) [y]: ").strip().lower()
if retry == 'n':
break
else:
print(f"\n{result}")
print("\n输入 'help' 查看帮助信息")
print("=" * 50)
# 主循环
while True:
try:
# 显示提示符
prompt = f"\n[{current_db_type.upper()}{'*' if connected else ''}]> "
command = input(prompt).strip()
if not command:
continue
# 处理特殊命令
cmd_lower = command.lower()
if cmd_lower in ['quit', 'exit']:
if connected:
print(db.close())
print("\n再见!")
break
elif cmd_lower == 'help':
print_help()
continue
elif cmd_lower == 'connect':
if connected:
print("已经连接到数据库")
else:
success, message = db.connect()
print(message)
connected = success
continue
elif cmd_lower == 'disconnect':
if not connected:
print("未连接到数据库")
else:
print(db.close())
connected = False
continue
elif cmd_lower == 'status':
status = "已连接" if connected else "未连接"
print(f"数据库类型: {current_db_type.upper()}")
print(f"连接状态: {status}")
if connected and hasattr(db, 'database') and db.database:
print(f"当前数据库: {db.database}")
continue
elif cmd_lower == 'show databases':
if not connected:
print("请先连接到数据库 (使用 'connect' 命令)")
elif not hasattr(db, 'list_databases'):
print("当前数据库类型不支持此命令")
else:
success, result = db.list_databases()
if success:
print("\n可用的数据库:")
for i, db_name in enumerate(result, 1):
print(f" {i}. {db_name}")
else:
print(f"\n{result}")
continue
elif cmd_lower.startswith('use '):
if not connected:
print("请先连接到数据库 (使用 'connect' 命令)")
elif not hasattr(db, 'use_database'):
print("当前数据库类型不支持此命令")
else:
db_input = command.split(maxsplit=1)[1].strip()
# 先获取数据库列表
list_success, db_list = db.list_databases()
# 判断是数字还是数据库名
selected_db = None
if db_input.isdigit() and list_success:
index = int(db_input) - 1
if 0 <= index < len(db_list):
selected_db = db_list[index]
else:
print(f"错误: 编号超出范围,请使用 'show databases' 查看可用数据库")
continue
else:
selected_db = db_input
# 尝试切换数据库
success, message = db.use_database(selected_db)
print(message)
# 如果失败,询问是否重试
if not success:
retry = input("是否重新输入数据库名? (y/n) [y]: ").strip().lower()
if retry != 'n':
while True:
new_db = input("请输入数据库名或编号: ").strip()
if not new_db:
break
# 再次判断数字或名称
if new_db.isdigit() and list_success:
idx = int(new_db) - 1
if 0 <= idx < len(db_list):
new_db = db_list[idx]
else:
print(f"错误: 编号超出范围")
continue
success2, message2 = db.use_database(new_db)
print(message2)
if success2:
break
retry_again = input("是否继续重试? (y/n) [y]: ").strip().lower()
if retry_again == 'n':
break
continue
elif cmd_lower.startswith('switch '):
new_type = cmd_lower.split()[1]
if new_type not in ['mysql', 'mongodb', 'redis', 'sqlite', 'postgres']:
print("无效的数据库类型!")
continue
# 关闭当前连接
if connected:
print(db.close())
connected = False
# 切换数据库
current_db_type = new_type
config = get_database_config(current_db_type)
db = create_database_instance(current_db_type, config)
print(f"已切换到 {current_db_type.upper()}")
continue
# 执行数据库命令
if not connected:
print("请先连接到数据库 (使用 'connect' 命令)")
continue
success, result = db.execute(command)
if success:
print(f"\n执行成功:")
print(format_output(result))
else:
print(f"\n执行失败:")
print(result)
except KeyboardInterrupt:
print("\n\n操作已取消")
continue
except EOFError:
print("\n\n再见!")
break
except Exception as e:
print(f"\n发生错误: {str(e)}")
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print("\n\n程序已退出")
sys.exit(0)