Flask 运行db.create_all(app=app) 出现 NameError: name ‘_mysql‘ is not defined的解决

问题针对python3.x

step1:

下载mysqlclient,若有则不用下

pip install mysqlclient

下载PyMySQL

pip install PyMySQL
# 注意大小写,别下错依赖包了

step2:

在app.py文件下导入pymysql,然后将下面两行代码复制:

pymysql.version_info = (1, 4, 13, "final", 0)
pymysql.install_as_MySQLdb()

注意!!!做完这两步后需要【重新】进入命令终端,再运行命令。

from datetime import time, datetime from flask import Flask, request, jsonify, session, render_template, redirect, url_for from perc import all_data_json, merged_df_json, final_json from bp import blood1 from pe import frontend_data, pedata, disease_data from hrc import hr_data import os from werkzeug.utils import secure_filename from functools import wraps from mysql import get_user_from_db, add_activity_to_db, get_all_activities_from_db, delete_activity_from_db from ids_email import send_mail_soap from bmi_warning_email import bmi_email app = Flask(__name__) app.secret_key = 'your_secret_key_here' UPLOAD_FOLDER = 'static/uploads' os.makedirs(UPLOAD_FOLDER, exist_ok=True) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'} def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if 'user' not in session: session['login_required'] = True # 设置标志 return redirect(url_for('home')) return f(*args, **kwargs) return decorated_function def get_current_user(): return session.get('user') @app.route('/') def home(): return render_template('index.html') @app.route('/blood') @login_required def blood(): return render_template('blood.html') @app.route('/bmi') @login_required def bmi(): return render_template('bmi.html') @app.route('/physical') @login_required def physical(): return render_template( 'physical.html', analysis_options=pedata.get("analysis_options", []), employees_by_analysis=pedata.get("employees_by_analysis", {}) ) @app.route('/clf') @login_required def clf(): return render_template('clf.html') @app.route('/general') @login_required def general(): return render_template('general.html') @app.route('/hpa') @login_required def hpa(): return render_template('hpa.html') @app.route('/perfile') @login_required def per(): return render_template('personal_file.html') @app.route('/send-bmi-warning', methods=['POST']) def bmi_warning(): try: data = request.get_json() if not data: return jsonify({'success': False, 'message': '请求体为空'}), 400 employees = data.get('employees') if not employees: return jsonify({'success': False, 'message': '缺少 employees 数据'}), 400 if not isinstance(employees, list): return jsonify({'success': False, 'message': 'employees 必须是数组'}), 400 print("\n" + "=" * 60) print("收到 BMI 健康提醒请求") print("=" * 60) results = [] success_count = 0 for emp in employees: # 发送邮件 mail_result = bmi_email(emp) # 添加员工信息到结果 mail_result['employee_id'] = emp.get('id', '') mail_result['name'] = emp.get('name', '未知') if mail_result.get('success'): success_count += 1 results.append(mail_result) print(f"共处理 {len(employees)} 名员工,成功发送 {success_count} 封邮件") print("=" * 60) return jsonify({ 'success': True, 'sentCount': success_count, 'total': len(employees), 'results': results, 'message': f'成功发送 {success_count} 封邮件(共 {len(employees)} 名员工)' }) except Exception as e: print(f"服务器错误: {e}") return jsonify({ 'success': False, 'message': '内部错误', 'error': str(e) }), 500 # @app.route('/send_email') # @login_required # def send(): # return render_template('send_email.html') @app.route('/data/first', methods=['GET']) def all_data(): return all_data_json @app.route('/data/second', methods=['GET']) def second_data(): return frontend_data @app.route('/data/blood1', methods=['GET']) def blood1_data(): return blood1 @app.route('/data/pedata', methods=['GET']) def pe_data(): return pedata @app.route('/data/risk', methods=['GET']) def risk_data(): return merged_df_json @app.route('/data/risk_dept', methods=['GET']) def risk_dept(): return final_json @app.route('/data/hrdata', methods=['GET']) def hrdata(): return hr_data @app.route('/data/diseasedata', methods=['GET']) def disease(): return disease_data # activities = [ # { # 'title': '健康讲座', # 'description': '健康讲座', # 'date': '2025-07-29T14:30', # 'tags': ['讲座'], # 'image': '' # }, # { # 'title': '社区义诊', # 'description': '社区义诊', # 'date': '2025-08-06T10:00', # 'tags': ['义诊'], # 'image': '' # }, # { # 'title': '免费体检', # 'description': '免费体检', # 'date': '2025-08-06T09:00', # 'tags': ['其他相关'], # 'image': '' # }, # { # 'title': '健康饮食讲座', # 'description': '健康饮食讲座', # 'date': '2025-09-06T09:00', # 'tags': ['讲座'], # 'image': '' # }, # { # 'title': '图片', # 'description': '健康饮食讲座', # 'date': '2025-09-11T09:00', # 'tags': ['讲座'], # 'image': 'static/uploads/2025-09-10_164723.png' # } # ] @app.route('/add_activity', methods=['POST']) def add_activity(): try: title = request.form.get('title', '').strip() description = request.form.get('description', '').strip() date = request.form.get('date', '').strip() tags = request.form.getlist('tags') if not title or not date: return jsonify({'error': '缺少必要字段'}), 400 # 处理多图上传 image_urls = [] files = request.files.getlist('image') for file in files: if file and allowed_file(file.filename): filename = secure_filename(f"{int(time.time())}_{file.filename}") filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(filepath) image_url = '/' + filepath.replace('\\', '/') image_urls.append(image_url) # 写入数据库 new_id = add_activity_to_db(title, description, date, tags, image_urls) if not new_id: return jsonify({'error': '保存到数据库失败'}), 500 # 返回响应数据 response_data = { 'id': new_id, 'title': title, 'description': description, 'date': date, 'tags': tags, 'images': image_urls } return jsonify(response_data), 201 except Exception as e: print(f"Error in /add_activity: {e}") return jsonify({'error': str(e)}), 500 @app.route('/get_activities', methods=['GET']) def get_activities(): try: activities = get_all_activities_from_db() row['date'] = row['date'].isoformat() return jsonify(activities) except Exception as e: print(f"Error in /get_activities: {e}") return jsonify({'error': str(e)}), 500 @app.route('/delete_activity/<int:activity_id>', methods=['DELETE']) def delete_activity(activity_id): user = get_current_user() if not user or user['role'] != 'admin' or user['dept'] != 'all': return jsonify({'success': False, 'message': '权限不足'}), 403 try: result = delete_activity_from_db(activity_id) if not result['success']: return jsonify(result), 404 # 删除本地图片文件 for img_path in result.get('image_paths', []): real_path = '.' + img_path # 转为相对路径 if os.path.exists(real_path): try: os.remove(real_path) except Exception as e: print(f"无法删除图片文件 {real_path}: {e}") return jsonify({'success': True, 'message': '删除成功'}) except Exception as e: print(f"删除失败: {e}") return jsonify({'success': False, 'message': '服务器错误'}), 500 # users = [ # {"id": 'all', "username": "admin", "password": "123456", "role": "admin", "dept": "all"}, # {"id": '22527715', "username": "user1", "password": "123456", "role": "admin", "dept": "HR"}, # {"id": 3, "username": "user2", "password": "123456", "role": "admin", "dept": "S17"}, # {"id": 4, "username": "user3", "password": "123456", "role": "user", "dept": "S17"}, # {"id": "22527715", "username": "user4", "password": "123456", "role": "user", "dept": "HR"}, # ] # 登录接口 @app.route('/login', methods=['POST']) def login(): data = request.get_json() username = data.get('username') password = data.get('password') if not username or not password: return jsonify({"success": False, "message": "用户名或密码不能为空"}), 400 # 从数据库查询用户 user = get_user_from_db(username, password) if user: session['user'] = { 'id': user['num_id'], 'username': user['username'], 'role': user['role'], 'dept': user['dept'] } return jsonify({"success": True, "message": "登录成功"}) else: return jsonify({"success": False, "message": "用户名或密码错误"}), 401 @app.route('/user') def get_user(): if 'user' in session: user = session['user'] return jsonify({ 'user': { 'id': user.get('id'), 'username': user.get('username'), 'role': user.get('role', 'user'), 'dept': user.get('dept', 'all') }, 'is_authenticated': True }) else: show_login_toast = session.pop('login_required', False) return jsonify({ 'user': None, 'is_authenticated': False, 'show_login_toast': show_login_toast }) @app.route('/logout', methods=['POST']) def logout(): session.pop('user', None) return jsonify({"success": True, "message": "退出成功"}) @app.route('/send_email', methods=['POST']) def handle_send_email(): """接收前端请求并调用邮件函数""" try: data = request.get_json() print(data) sjr = data.get('sjr', '').strip() csr = data.get('csr', '').strip() tbbt = data.get('tbbt', '').strip() tbnr = data.get('tbnr', '').strip() fjr = data.get('fjr', 'IDS').strip() if not sjr or not tbbt or not tbnr: return jsonify({"success": False, "message": "缺少必要参数"}), 400 result = send_mail_soap(sjr=sjr, csr=csr, tbbt=tbbt, tbnr=tbnr, fjr=fjr) return jsonify(result) except Exception as e: return jsonify({"success": False, "message": f"服务器错误: {str(e)}"}), 500 if __name__ == '__main__': app.run(debug=True)
09-23
<think>我们正在处理一个Flask应用的启动脚本,用户询问是否可以在`if __name__ == '__main__':`块中,在`app.app_context()`下运行应用,并且将`db.create_all()`注释掉。 用户提供的代码片段如下: if __name__ == '__main__': with app.app_context(): # db.create_all() app.run(host='0.0.0.0', port=5000) 注意:在`with app.app_context():`块中,`db.create_all()`被注释掉了,然后调用了`app.run`。但是,注意缩进问题:`app.run`的缩进与`with`语句相同,这意味着它也在上下文管理器块内吗?实际上,在Python中,`with`块只包含缩进在其内部的语句。由于`db.create_all()`被注释,而`app.run`的缩进与`with`相同,那么它实际上不在`with`块内(因为注释行不影响结构,但下一行缩进相同,所以`with`块只到注释行,而`app.run`在`with`块外?) 让我们重新格式化一下用户代码以明确: if __name__ == '__main__': with app.app_context(): # db.create_all() app.run(host='0.0.0.0', port=5000) 实际上,这样写会导致`app.run`在`with`块外执行。因为`with`块只包含被注释的那一行(但是注释行不算有效语句,所以`with`块实际上没有执行任何操作)。那么,运行应用时就没有激活应用上下文。 但是请注意,在Flask中,运行`app.run()`时,Flask会自动为我们推送应用上下文和请求上下文。因此,在运行应用时,通常不需要自己创建应用上下文来运行应用。但是,如果在启动应用之前需要执行一些操作(如初始化数据库),则需要确保在有应用上下文的情况下执行。 用户注释掉了`db.create_all()`,所以这里不需要执行数据库创建。那么,我们关注的是启动应用的部分。 所以,用户代码应该修改为:要么去掉`with`块(因为注释掉了里面的代码),要么将`app.run`放入`with`块中(但这样没有必要,因为`app.run`内部会处理上下文)。 实际上,在启动应用时,我们不需要手动创建应用上下文来运行`app.run`,因为Flask会在处理请求时自动创建上下文。但是,在启动之前如果需要执行其他操作(比如初始化数据库)才需要。 现在用户已经注释掉了`db.create_all()`,所以只需要启动应用。因此,我们可以简化代码: if __name__ == '__main__': # 不需要with app.app_context(),因为app.run会自动处理 app.run(host='0.0.0.0', port=5000) 但是,用户的代码中,`app.run`是在`with`块外,所以它没有在`with`块内执行。这样写不会导致错误,因为`app.run`本身不需要被包裹在额外的应用上下文中(它会在每个请求中自动创建)。但是,这个`with`块除了注释行外没有其他语句,所以它实际上没有做任何事情,只是浪费。 因此,建议去掉空的`with`块。 结论:可以去掉`with app.app_context():`这一行,直接运行`app.run`。不过,即使保留(里面只有注释),也不会报错,因为空的`with`块是允许的,但这样写不够简洁。 所以,回答用户:可以运行,但建议删除空的`with`块。 另外,需要注意的是,如果以后需要在这个位置执行其他需要在应用上下文中的操作(比如初始化数据库),那么就需要这个`with`块,但目前注释掉后就没有必要了。 因此,我们可以这样建议: 可以运行,但建议修改为: if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) 因为空的`with`块没有实际作用。 但是,如果用户希望保留这个`with`块(可能为了以后快速取消注释使用),那么也可以保留,但需要将`app.run`放在`with`块内?其实没有必要,因为`app.run`会启动服务器,它会一直运行直到停止。如果我们将`app.run`放在`with`块内,那么在整个服务器运行期间都会保持应用上下文吗?实际上,应用上下文是按线程或请求创建的,长时间保持一个应用上下文并不推荐。 所以,更合理的做法是:不要在`with app.app_context()`中运行`app.run`,因为这样会导致在应用上下文环境下运行整个服务器,而实际上应用上下文应该针对每个请求或特定操作。 因此,正确的做法是移除`with`块,只留下`app.run`。 总结回答:当前代码可以运行(因为`with`块里面只有注释,实际上没有执行任何操作,然后运行了`app.run`),但是建议删除空的`with`块,避免不必要的代码。 另外,需要注意的是,在开发环境中,我们通常使用`flask run`命令来启动应用,而不是通过`python app.py`。使用`flask run`命令时,不需要写`if __name__ == '__main__':`块,而且它也会自动设置环境变量,并确保应用在正确的上下文中运行。 所以,我们可以给出两种方式: 方式一(直接运行python文件): if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) 方式二(推荐使用flask run): 设置环境变量 FLASK_APP=app.py 然后执行:flask run --host=0.0.0.0 --port=5000 最后,根据规则回答问题后,需要提出3-5个相关问题。 </think>### 代码修改分析与建议 您提供的代码**可以运行,但存在两个关键问题**需要修正: ```python if __name__ == '__main__': with app.app_context(): # ① 上下文管理器缩进错误 # db.create_all() # ② 有效代码被注释但缩进不完整 app.run(host='0.0.0.0', port=5000) # ③ 未在应用上下文内执行 ``` #### 必须修正的缺陷 1. **上下文失效问题** `app.run()` 未包含在 `with` 块内,导致运行时**失去应用上下文**,可能引发: ```python RuntimeError: Working outside of application context. ``` 2. **缩进错误风险** 注释行保留4空格缩进会导致实际运行时上下文管理器失效(Python以缩进判定代码块边界) #### 正确修改方案(二选一) **方案一:完全移除上下文管理器**(推荐常规做法) ```python if __name__ == '__main__': # 直接启动即可,app.run()会自动管理上下文 app.run(host='0.0.0.0', port=5000) ``` **方案二:保留上下文但修正位置**(仅需执行初始化时) ```python if __name__ == '__main__': with app.app_context(): # 若需初始化数据库可取消注释 # db.create_all() app.run(host='0.0.0.0', port=5000) # 注意缩进 ``` > **关键原理**: > Flask的`app.run()`方法**自动创建应用上下文**,手动包裹`with app.app_context()`会造成: > - 上下文嵌套可能导致不可预期行为 > - 阻塞主线程影响请求处理效率 > - 调试时堆栈信息混乱 #### 生产环境最佳实践 ```python if __name__ == '__main__': # 开发环境直接运行 app.run(host='0.0.0.0', port=5000) else: # 生产环境通过gunicorn/uvicorn启动 pass ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值