More convenient project initialization, with database initialization added to app.py.
Showing
5 changed files
with
185 additions
and
90 deletions
app.log
0 → 100644
| 1 | -from flask import Flask, session, request, redirect, render_template | 1 | +import os |
| 2 | import re | 2 | import re |
| 3 | -from apscheduler.schedulers.background import BackgroundScheduler | 3 | +import logging |
| 4 | +import getpass | ||
| 5 | +import pymysql | ||
| 4 | import subprocess | 6 | import subprocess |
| 5 | -import os | 7 | +from flask import Flask, session, request, redirect, render_template |
| 8 | +from apscheduler.schedulers.background import BackgroundScheduler | ||
| 6 | from pytz import utc | 9 | from pytz import utc |
| 7 | -import logging | 10 | + |
| 11 | +# 初始化日志记录 | ||
| 12 | +logging.basicConfig( | ||
| 13 | + level=logging.INFO, | ||
| 14 | + format='%(asctime)s [%(levelname)s] %(message)s', | ||
| 15 | + handlers=[ | ||
| 16 | + logging.FileHandler("app.log"), | ||
| 17 | + logging.StreamHandler() | ||
| 18 | + ] | ||
| 19 | +) | ||
| 20 | + | ||
| 21 | +def get_db_connection_interactive(): | ||
| 22 | + """ | ||
| 23 | + 通过终端交互获取数据库连接参数,若按回车则使用默认值。 | ||
| 24 | + 返回一个连接对象。 | ||
| 25 | + """ | ||
| 26 | + print("请依次输入数据库连接信息(直接按回车使用默认值):") | ||
| 27 | + | ||
| 28 | + host = input(" 1. 主机 (默认: localhost): ") or "localhost" | ||
| 29 | + port_str = input(" 2. 端口 (默认: 3306): ") or "3306" | ||
| 30 | + try: | ||
| 31 | + port = int(port_str) | ||
| 32 | + except ValueError: | ||
| 33 | + logging.warning("端口号无效,使用默认端口 3306。") | ||
| 34 | + port = 3306 | ||
| 35 | + | ||
| 36 | + user = input(" 3. 用户名 (默认: root): ") or "root" | ||
| 37 | + password = getpass.getpass(" 4. 密码 (默认: 12345678): ") or "12345678" | ||
| 38 | + db_name = input(" 5. 数据库名 (默认: Weibo_PublicOpinion_AnalysisSystem): ") or "Weibo_PublicOpinion_AnalysisSystem" | ||
| 39 | + | ||
| 40 | + logging.info(f"尝试连接到数据库: {user}@{host}:{port}/{db_name}") | ||
| 41 | + | ||
| 42 | + try: | ||
| 43 | + connection = pymysql.connect( | ||
| 44 | + host=host, | ||
| 45 | + port=port, | ||
| 46 | + user=user, | ||
| 47 | + password=password, | ||
| 48 | + database=db_name, | ||
| 49 | + charset='utf8mb4', | ||
| 50 | + cursorclass=pymysql.cursors.DictCursor # 返回字典格式 | ||
| 51 | + ) | ||
| 52 | + logging.info("数据库连接成功。") | ||
| 53 | + return connection | ||
| 54 | + except pymysql.MySQLError as e: | ||
| 55 | + logging.error(f"数据库连接失败: {e}") | ||
| 56 | + exit(1) | ||
| 57 | + | ||
| 58 | +def initialize_database(connection, sql_file_path): | ||
| 59 | + """ | ||
| 60 | + 执行 SQL 文件中的语句以初始化数据库。 | ||
| 61 | + | ||
| 62 | + :param connection: 已建立的数据库连接 | ||
| 63 | + :param sql_file_path: SQL 文件的路径 | ||
| 64 | + """ | ||
| 65 | + try: | ||
| 66 | + with open(sql_file_path, 'r', encoding='utf8') as file: | ||
| 67 | + sql_commands = file.read() | ||
| 68 | + | ||
| 69 | + with connection.cursor() as cursor: | ||
| 70 | + for statement in sql_commands.split(';'): | ||
| 71 | + statement = statement.strip() | ||
| 72 | + if statement: | ||
| 73 | + cursor.execute(statement) | ||
| 74 | + connection.commit() | ||
| 75 | + logging.info("数据库初始化成功。") | ||
| 76 | + except FileNotFoundError: | ||
| 77 | + logging.error(f"SQL 文件未找到: {sql_file_path}") | ||
| 78 | + exit(1) | ||
| 79 | + except pymysql.MySQLError as e: | ||
| 80 | + logging.error(f"执行 SQL 时出错: {e}") | ||
| 81 | + connection.rollback() | ||
| 82 | + exit(1) | ||
| 83 | + except Exception as e: | ||
| 84 | + logging.error(f"初始化数据库时出错: {e}") | ||
| 85 | + connection.rollback() | ||
| 86 | + exit(1) | ||
| 87 | + | ||
| 88 | +def prompt_first_run(): | ||
| 89 | + """ | ||
| 90 | + 询问用户是否首次运行,需要初始化数据库。 | ||
| 91 | + | ||
| 92 | + :return: Boolean,True 表示需要初始化数据库 | ||
| 93 | + """ | ||
| 94 | + while True: | ||
| 95 | + choice = input("是否首次运行该项目,需要初始化数据库?(Y/n): ").strip().lower() | ||
| 96 | + if choice in ['y', 'yes', '']: | ||
| 97 | + return True | ||
| 98 | + elif choice in ['n', 'no']: | ||
| 99 | + return False | ||
| 100 | + else: | ||
| 101 | + print("请输入 Y 或 N。") | ||
| 8 | 102 | ||
| 9 | # 初始化 Flask 应用 | 103 | # 初始化 Flask 应用 |
| 10 | app = Flask(__name__) | 104 | app = Flask(__name__) |
| @@ -14,25 +108,13 @@ app.secret_key = 'this is secret_key you know ?' # 设置 Flask 的密钥,用 | @@ -14,25 +108,13 @@ app.secret_key = 'this is secret_key you know ?' # 设置 Flask 的密钥,用 | ||
| 14 | from views.page import page | 108 | from views.page import page |
| 15 | from views.user import user | 109 | from views.user import user |
| 16 | app.register_blueprint(page.pb) # 注册页面蓝图 | 110 | app.register_blueprint(page.pb) # 注册页面蓝图 |
| 17 | -app.register_blueprint(user.ub) # 注册用户蓝图 | 111 | +app.register_blueprint(user.ub) # 注册用户蓝图 |
| 18 | 112 | ||
| 19 | # 首页路由,清空 session | 113 | # 首页路由,清空 session |
| 20 | @app.route('/') | 114 | @app.route('/') |
| 21 | def hello_world(): | 115 | def hello_world(): |
| 22 | - return session.clear() # 清空 session,用户退出登录 | ||
| 23 | - | ||
| 24 | -""" | ||
| 25 | -@app.before_request | ||
| 26 | -def before_reuqest(): | ||
| 27 | - pat = re.compile(r'^/static') # 正则匹配静态文件路径 | ||
| 28 | - if re.search(pat, request.path): # 如果是静态文件,直接返回 | ||
| 29 | - return | ||
| 30 | - elif request.path == '/user/login' or request.path == '/user/register': # 登录或注册页面无需验证 | ||
| 31 | - return | ||
| 32 | - elif session.get('username'): # 如果 session 中有用户名,则允许继续 | ||
| 33 | - return | ||
| 34 | - return redirect('/user/login') # 否则重定向到登录页面 | ||
| 35 | -""" | 116 | + session.clear() # 清空 session,用户退出登录 |
| 117 | + return "Session Cleared" | ||
| 36 | 118 | ||
| 37 | # 中间件:处理请求前的逻辑 | 119 | # 中间件:处理请求前的逻辑 |
| 38 | @app.before_request | 120 | @app.before_request |
| @@ -79,6 +161,19 @@ def run_script(): | @@ -79,6 +161,19 @@ def run_script(): | ||
| 79 | 161 | ||
| 80 | # 主程序入口 | 162 | # 主程序入口 |
| 81 | if __name__ == '__main__': | 163 | if __name__ == '__main__': |
| 164 | + # 检测是否需要初始化数据库 | ||
| 165 | + if prompt_first_run(): | ||
| 166 | + # 获取数据库连接 | ||
| 167 | + connection = get_db_connection_interactive() | ||
| 168 | + | ||
| 169 | + # 执行数据库初始化 | ||
| 170 | + sql_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'createTables.sql') | ||
| 171 | + initialize_database(connection, sql_file) | ||
| 172 | + | ||
| 173 | + # 关闭数据库连接 | ||
| 174 | + connection.close() | ||
| 175 | + logging.info("数据库连接已关闭。") | ||
| 176 | + | ||
| 82 | # 设置定时任务,定期执行爬虫脚本 | 177 | # 设置定时任务,定期执行爬虫脚本 |
| 83 | scheduler = BackgroundScheduler(timezone=utc) # 创建后台任务调度器 | 178 | scheduler = BackgroundScheduler(timezone=utc) # 创建后台任务调度器 |
| 84 | scheduler.add_job(run_script, 'interval', hours=5) # 每5小时执行一次爬虫脚本 | 179 | scheduler.add_job(run_script, 'interval', hours=5) # 每5小时执行一次爬虫脚本 |
| @@ -90,8 +185,6 @@ if __name__ == '__main__': | @@ -90,8 +185,6 @@ if __name__ == '__main__': | ||
| 90 | scheduler.shutdown() # 确保在应用关闭时关闭调度器 | 185 | scheduler.shutdown() # 确保在应用关闭时关闭调度器 |
| 91 | 186 | ||
| 92 | # 设置日志记录,捕获应用的请求信息 | 187 | # 设置日志记录,捕获应用的请求信息 |
| 93 | -logging.basicConfig(level=logging.INFO) # 配置日志记录,设置日志级别为 INFO | ||
| 94 | - | ||
| 95 | @app.before_request | 188 | @app.before_request |
| 96 | def log_request_info(): | 189 | def log_request_info(): |
| 97 | # 记录每次请求的信息,便于调试和监控 | 190 | # 记录每次请求的信息,便于调试和监控 |
database_operations.log
0 → 100644
| @@ -4,7 +4,7 @@ from sqlalchemy import create_engine | @@ -4,7 +4,7 @@ from sqlalchemy import create_engine | ||
| 4 | from getpass import getpass | 4 | from getpass import getpass |
| 5 | import logging | 5 | import logging |
| 6 | 6 | ||
| 7 | -# 配置日志 | 7 | +# 配置日志 |
| 8 | logging.basicConfig( | 8 | logging.basicConfig( |
| 9 | level=logging.INFO, | 9 | level=logging.INFO, |
| 10 | format='%(asctime)s [%(levelname)s] %(message)s', | 10 | format='%(asctime)s [%(levelname)s] %(message)s', |
| @@ -14,95 +14,95 @@ logging.basicConfig( | @@ -14,95 +14,95 @@ logging.basicConfig( | ||
| 14 | ] | 14 | ] |
| 15 | ) | 15 | ) |
| 16 | 16 | ||
| 17 | -# 假设 articleAddr 和 commentsAddr 是绝对路径或相对于脚本的路径 | 17 | +# 假设 articleAddr 和 commentsAddr 是绝对路径或相对于脚本的路径 |
| 18 | from spiderDataPackage.settings import articleAddr, commentsAddr | 18 | from spiderDataPackage.settings import articleAddr, commentsAddr |
| 19 | 19 | ||
| 20 | def get_db_connection_interactive(): | 20 | def get_db_connection_interactive(): |
| 21 | """ | 21 | """ |
| 22 | - 通过终端交互获取数据库连接参数,若按回车则使用默认值。 | ||
| 23 | - 返回 SQLAlchemy 的数据库引擎。 | 22 | + 通过终端交互获取数据库连接参数,若按回车则使用默认值。 |
| 23 | + 返回 SQLAlchemy 的数据库引擎。 | ||
| 24 | """ | 24 | """ |
| 25 | - print("请依次输入数据库连接信息(直接按回车使用默认值):") | 25 | + print("请依次输入数据库连接信息(直接按回车使用默认值):") |
| 26 | 26 | ||
| 27 | - host = input(" 1. 主机 (默认: localhost): ") or "localhost" | ||
| 28 | - port_str = input(" 2. 端口 (默认: 3306): ") or "3306" | 27 | + host = input(" 1. 主机 (默认: localhost): ") or "localhost" |
| 28 | + port_str = input(" 2. 端口 (默认: 3306): ") or "3306" | ||
| 29 | try: | 29 | try: |
| 30 | port = int(port_str) | 30 | port = int(port_str) |
| 31 | except ValueError: | 31 | except ValueError: |
| 32 | - logging.warning("端口号无效,使用默认端口 3306。") | 32 | + logging.warning("端口号无效,使用默认端口 3306。") |
| 33 | port = 3306 | 33 | port = 3306 |
| 34 | 34 | ||
| 35 | - user = input(" 3. 用户名 (默认: root): ") or "root" | ||
| 36 | - password = getpass(" 4. 密码 (默认: 12345678): ") or "12345678" | ||
| 37 | - db_name = input(" 5. 数据库名 (默认: Weibo_PublicOpinion_AnalysisSystem): ") or "Weibo_PublicOpinion_AnalysisSystem" | 35 | + user = input(" 3. 用户名 (默认: root): ") or "root" |
| 36 | + password = getpass(" 4. 密码 (默认: 12345678): ") or "12345678" | ||
| 37 | + db_name = input(" 5. 数据库名 (默认: Weibo_PublicOpinion_AnalysisSystem): ") or "Weibo_PublicOpinion_AnalysisSystem" | ||
| 38 | 38 | ||
| 39 | - # 构建数据库连接字符串 | 39 | + # 构建数据库连接字符串 |
| 40 | connection_str = f"mysql+pymysql://{user}:{password}@{host}:{port}/{db_name}?charset=utf8mb4" | 40 | connection_str = f"mysql+pymysql://{user}:{password}@{host}:{port}/{db_name}?charset=utf8mb4" |
| 41 | 41 | ||
| 42 | try: | 42 | try: |
| 43 | engine = create_engine(connection_str) | 43 | engine = create_engine(connection_str) |
| 44 | - # 测试连接 | 44 | + # 测试连接 |
| 45 | with engine.connect() as connection: | 45 | with engine.connect() as connection: |
| 46 | - logging.info(f"成功连接到数据库: {user}@{host}:{port}/{db_name}") | 46 | + logging.info(f"成功连接到数据库: {user}@{host}:{port}/{db_name}") |
| 47 | return engine | 47 | return engine |
| 48 | except Exception as e: | 48 | except Exception as e: |
| 49 | - logging.error(f"无法连接到数据库: {e}") | 49 | + logging.error(f"无法连接到数据库: {e}") |
| 50 | exit(1) | 50 | exit(1) |
| 51 | 51 | ||
| 52 | def saveData(engine): | 52 | def saveData(engine): |
| 53 | """ | 53 | """ |
| 54 | - 从数据库和CSV文件读取数据,合并后去重并保存回数据库。 | ||
| 55 | - 最后删除CSV文件。 | 54 | + 从数据库和CSV文件读取数据,合并后去重并保存回数据库。 |
| 55 | + 最后删除CSV文件。 | ||
| 56 | """ | 56 | """ |
| 57 | try: | 57 | try: |
| 58 | - # 读取旧数据 | 58 | + # 读取旧数据 |
| 59 | oldArticle = pd.read_sql('SELECT * FROM article', engine) | 59 | oldArticle = pd.read_sql('SELECT * FROM article', engine) |
| 60 | oldComment = pd.read_sql('SELECT * FROM comments', engine) | 60 | oldComment = pd.read_sql('SELECT * FROM comments', engine) |
| 61 | - logging.info("成功从数据库读取旧的文章和评论数据。") | 61 | + logging.info("成功从数据库读取旧的文章和评论数据。") |
| 62 | 62 | ||
| 63 | - # 读取新数据 | 63 | + # 读取新数据 |
| 64 | newArticle = pd.read_csv(articleAddr) | 64 | newArticle = pd.read_csv(articleAddr) |
| 65 | newComment = pd.read_csv(commentsAddr) | 65 | newComment = pd.read_csv(commentsAddr) |
| 66 | - logging.info("成功从CSV文件读取新的文章和评论数据。") | 66 | + logging.info("成功从CSV文件读取新的文章和评论数据。") |
| 67 | 67 | ||
| 68 | - # 合并数据 | 68 | + # 合并数据 |
| 69 | mergeArticle = pd.concat([newArticle, oldArticle], ignore_index=True, sort=False) | 69 | mergeArticle = pd.concat([newArticle, oldArticle], ignore_index=True, sort=False) |
| 70 | mergeComment = pd.concat([newComment, oldComment], ignore_index=True, sort=False) | 70 | mergeComment = pd.concat([newComment, oldComment], ignore_index=True, sort=False) |
| 71 | - logging.info("成功合并新旧文章和评论数据。") | 71 | + logging.info("成功合并新旧文章和评论数据。") |
| 72 | 72 | ||
| 73 | - # 去重 | 73 | + # 去重 |
| 74 | mergeArticle.drop_duplicates(subset='id', keep='last', inplace=True) | 74 | mergeArticle.drop_duplicates(subset='id', keep='last', inplace=True) |
| 75 | mergeComment.drop_duplicates(subset='content', keep='last', inplace=True) | 75 | mergeComment.drop_duplicates(subset='content', keep='last', inplace=True) |
| 76 | - logging.info("成功去除重复的文章和评论数据。") | 76 | + logging.info("成功去除重复的文章和评论数据。") |
| 77 | 77 | ||
| 78 | - # 保存回数据库 | 78 | + # 保存回数据库 |
| 79 | mergeArticle.to_sql('article', con=engine, if_exists='replace', index=False) | 79 | mergeArticle.to_sql('article', con=engine, if_exists='replace', index=False) |
| 80 | mergeComment.to_sql('comments', con=engine, if_exists='replace', index=False) | 80 | mergeComment.to_sql('comments', con=engine, if_exists='replace', index=False) |
| 81 | - logging.info("成功将合并后的数据保存回数据库。") | 81 | + logging.info("成功将合并后的数据保存回数据库。") |
| 82 | 82 | ||
| 83 | except pd.errors.EmptyDataError as e: | 83 | except pd.errors.EmptyDataError as e: |
| 84 | - logging.error(f"读取CSV文件时出错: {e}") | 84 | + logging.error(f"读取CSV文件时出错: {e}") |
| 85 | except Exception as e: | 85 | except Exception as e: |
| 86 | - logging.error(f"保存数据时出错: {e}") | 86 | + logging.error(f"保存数据时出错: {e}") |
| 87 | else: | 87 | else: |
| 88 | - # 删除CSV文件 | 88 | + # 删除CSV文件 |
| 89 | try: | 89 | try: |
| 90 | os.remove(articleAddr) | 90 | os.remove(articleAddr) |
| 91 | os.remove(commentsAddr) | 91 | os.remove(commentsAddr) |
| 92 | - logging.info("成功删除CSV文件。") | 92 | + logging.info("成功删除CSV文件。") |
| 93 | except Exception as e: | 93 | except Exception as e: |
| 94 | - logging.warning(f"删除CSV文件时出错: {e}") | 94 | + logging.warning(f"删除CSV文件时出错: {e}") |
| 95 | 95 | ||
| 96 | def main(): | 96 | def main(): |
| 97 | - # 获取数据库连接 | 97 | + # 获取数据库连接 |
| 98 | engine = get_db_connection_interactive() | 98 | engine = get_db_connection_interactive() |
| 99 | 99 | ||
| 100 | - # 保存数据 | 100 | + # 保存数据 |
| 101 | saveData(engine) | 101 | saveData(engine) |
| 102 | 102 | ||
| 103 | - # 关闭引擎(可选,因为SQLAlchemy引擎会自动管理连接池) | 103 | + # 关闭引擎(可选,因为SQLAlchemy引擎会自动管理连接池) |
| 104 | engine.dispose() | 104 | engine.dispose() |
| 105 | - logging.info("数据库连接已关闭。") | 105 | + logging.info("数据库连接已关闭。") |
| 106 | 106 | ||
| 107 | if __name__ == '__main__': | 107 | if __name__ == '__main__': |
| 108 | main() | 108 | main() |
| @@ -2,7 +2,7 @@ import getpass | @@ -2,7 +2,7 @@ import getpass | ||
| 2 | import pymysql | 2 | import pymysql |
| 3 | import logging | 3 | import logging |
| 4 | 4 | ||
| 5 | -# 配置日志 | 5 | +# 配置日志 |
| 6 | logging.basicConfig( | 6 | logging.basicConfig( |
| 7 | level=logging.INFO, | 7 | level=logging.INFO, |
| 8 | format='%(asctime)s [%(levelname)s] %(message)s', | 8 | format='%(asctime)s [%(levelname)s] %(message)s', |
| @@ -14,24 +14,24 @@ logging.basicConfig( | @@ -14,24 +14,24 @@ logging.basicConfig( | ||
| 14 | 14 | ||
| 15 | def get_db_connection_interactive(): | 15 | def get_db_connection_interactive(): |
| 16 | """ | 16 | """ |
| 17 | - 通过终端交互获取数据库连接参数,若按回车则使用默认值。 | ||
| 18 | - 返回一个连接对象。 | 17 | + 通过终端交互获取数据库连接参数,若按回车则使用默认值。 |
| 18 | + 返回一个连接对象。 | ||
| 19 | """ | 19 | """ |
| 20 | - print("请依次输入数据库连接信息(直接按回车使用默认值):") | 20 | + print("请依次输入数据库连接信息(直接按回车使用默认值):") |
| 21 | 21 | ||
| 22 | - host = input(" 1. 主机 (默认: localhost): ") or "localhost" | ||
| 23 | - port_str = input(" 2. 端口 (默认: 3306): ") or "3306" | 22 | + host = input(" 1. 主机 (默认: localhost): ") or "localhost" |
| 23 | + port_str = input(" 2. 端口 (默认: 3306): ") or "3306" | ||
| 24 | try: | 24 | try: |
| 25 | port = int(port_str) | 25 | port = int(port_str) |
| 26 | except ValueError: | 26 | except ValueError: |
| 27 | - logging.warning("端口号无效,使用默认端口 3306。") | 27 | + logging.warning("端口号无效,使用默认端口 3306。") |
| 28 | port = 3306 | 28 | port = 3306 |
| 29 | 29 | ||
| 30 | - user = input(" 3. 用户名 (默认: root): ") or "root" | ||
| 31 | - password = getpass.getpass(" 4. 密码 (默认: 312517): ") or "312517" | ||
| 32 | - db_name = input(" 5. 数据库名 (默认: Weibo_PublicOpinion_AnalysisSystem): ") or "Weibo_PublicOpinion_AnalysisSystem" | 30 | + user = input(" 3. 用户名 (默认: root): ") or "root" |
| 31 | + password = getpass.getpass(" 4. 密码 (默认: 12345678): ") or "12345678" | ||
| 32 | + db_name = input(" 5. 数据库名 (默认: Weibo_PublicOpinion_AnalysisSystem): ") or "Weibo_PublicOpinion_AnalysisSystem" | ||
| 33 | 33 | ||
| 34 | - logging.info(f"尝试连接到数据库: {user}@{host}:{port}/{db_name}") | 34 | + logging.info(f"尝试连接到数据库: {user}@{host}:{port}/{db_name}") |
| 35 | 35 | ||
| 36 | try: | 36 | try: |
| 37 | connection = pymysql.connect( | 37 | connection = pymysql.connect( |
| @@ -41,29 +41,29 @@ def get_db_connection_interactive(): | @@ -41,29 +41,29 @@ def get_db_connection_interactive(): | ||
| 41 | password=password, | 41 | password=password, |
| 42 | database=db_name, | 42 | database=db_name, |
| 43 | charset='utf8mb4', | 43 | charset='utf8mb4', |
| 44 | - cursorclass=pymysql.cursors.DictCursor # 返回字典格式 | 44 | + cursorclass=pymysql.cursors.DictCursor # 返回字典格式 |
| 45 | ) | 45 | ) |
| 46 | - logging.info("数据库连接成功。") | 46 | + logging.info("数据库连接成功。") |
| 47 | return connection | 47 | return connection |
| 48 | except pymysql.MySQLError as e: | 48 | except pymysql.MySQLError as e: |
| 49 | - logging.error(f"数据库连接失败: {e}") | 49 | + logging.error(f"数据库连接失败: {e}") |
| 50 | exit(1) | 50 | exit(1) |
| 51 | 51 | ||
| 52 | -# 获取数据库连接 | 52 | +# 获取数据库连接 |
| 53 | conn = get_db_connection_interactive() | 53 | conn = get_db_connection_interactive() |
| 54 | 54 | ||
| 55 | -# 获取游标 | 55 | +# 获取游标 |
| 56 | cursor = conn.cursor() | 56 | cursor = conn.cursor() |
| 57 | 57 | ||
| 58 | def query(sql, params=None, query_type="no_select"): | 58 | def query(sql, params=None, query_type="no_select"): |
| 59 | """ | 59 | """ |
| 60 | - 执行SQL查询或操作。 | 60 | + 执行SQL查询或操作。 |
| 61 | 61 | ||
| 62 | - :param sql: SQL语句 | ||
| 63 | - :param params: SQL参数(可选) | ||
| 64 | - :param query_type: 查询类型,默认为 "no_select" | ||
| 65 | - 如果不是 "no_select",则执行 fetch 操作 | ||
| 66 | - :return: 如果是查询操作,返回数据列表;否则返回 None | 62 | + :param sql: SQL语句 |
| 63 | + :param params: SQL参数(可选) | ||
| 64 | + :param query_type: 查询类型,默认为 "no_select" | ||
| 65 | + 如果不是 "no_select",则执行 fetch 操作 | ||
| 66 | + :return: 如果是查询操作,返回数据列表;否则返回 None | ||
| 67 | """ | 67 | """ |
| 68 | try: | 68 | try: |
| 69 | if params: | 69 | if params: |
| @@ -72,43 +72,43 @@ def query(sql, params=None, query_type="no_select"): | @@ -72,43 +72,43 @@ def query(sql, params=None, query_type="no_select"): | ||
| 72 | else: | 72 | else: |
| 73 | cursor.execute(sql) | 73 | cursor.execute(sql) |
| 74 | 74 | ||
| 75 | - # 确保连接保持活跃 | 75 | + # 确保连接保持活跃 |
| 76 | conn.ping(reconnect=True) | 76 | conn.ping(reconnect=True) |
| 77 | 77 | ||
| 78 | if query_type != "no_select": | 78 | if query_type != "no_select": |
| 79 | data_list = cursor.fetchall() | 79 | data_list = cursor.fetchall() |
| 80 | conn.commit() | 80 | conn.commit() |
| 81 | - logging.info("查询成功,已获取数据。") | 81 | + logging.info("查询成功,已获取数据。") |
| 82 | return data_list | 82 | return data_list |
| 83 | else: | 83 | else: |
| 84 | conn.commit() | 84 | conn.commit() |
| 85 | - logging.info("操作成功,已提交事务。") | 85 | + logging.info("操作成功,已提交事务。") |
| 86 | except pymysql.MySQLError as e: | 86 | except pymysql.MySQLError as e: |
| 87 | - logging.error(f"执行SQL时出错: {e}") | 87 | + logging.error(f"执行SQL时出错: {e}") |
| 88 | conn.rollback() | 88 | conn.rollback() |
| 89 | return None | 89 | return None |
| 90 | 90 | ||
| 91 | def main(): | 91 | def main(): |
| 92 | - # 示例用法 | 92 | + # 示例用法 |
| 93 | 93 | ||
| 94 | - # 执行查询操作 | 94 | + # 执行查询操作 |
| 95 | select_sql = "SELECT * FROM article LIMIT 5" | 95 | select_sql = "SELECT * FROM article LIMIT 5" |
| 96 | articles = query(select_sql, query_type="select") | 96 | articles = query(select_sql, query_type="select") |
| 97 | if articles: | 97 | if articles: |
| 98 | for article in articles: | 98 | for article in articles: |
| 99 | print(article) | 99 | print(article) |
| 100 | 100 | ||
| 101 | - # 执行插入操作(根据实际表结构修改) | 101 | + # 执行插入操作(根据实际表结构修改) |
| 102 | insert_sql = "INSERT INTO article (id, content) VALUES (%s, %s)" | 102 | insert_sql = "INSERT INTO article (id, content) VALUES (%s, %s)" |
| 103 | - new_article = (12345, "这是一条新的文章内容。") | 103 | + new_article = (12345, "这是一条新的文章内容。") |
| 104 | result = query(insert_sql, params=new_article, query_type="no_select") | 104 | result = query(insert_sql, params=new_article, query_type="no_select") |
| 105 | if result is None: | 105 | if result is None: |
| 106 | - logging.info("插入操作完成。") | 106 | + logging.info("插入操作完成。") |
| 107 | 107 | ||
| 108 | - # 关闭游标和连接 | 108 | + # 关闭游标和连接 |
| 109 | cursor.close() | 109 | cursor.close() |
| 110 | conn.close() | 110 | conn.close() |
| 111 | - logging.info("数据库连接已关闭。") | 111 | + logging.info("数据库连接已关闭。") |
| 112 | 112 | ||
| 113 | if __name__ == '__main__': | 113 | if __name__ == '__main__': |
| 114 | main() | 114 | main() |
-
Please register or login to post a comment