-
1、PyCharm安装Python时的常见pip报错原因与解决方案全解析【转载】cid:link_02、Python中修复中文乱码的7种场景方法介绍【转载】cid:link_13、深入解析Python命名空间与作用域的核心机制【转载】cid:link_24、Git忽略大小写(重命名文件)的解决办法【转载】cid:link_35、git push常见问题及解决方案【转载】cid:link_46、一文详解Git的暂存与stash功能【转载】cid:link_57、Git合并后回退操作的完整指南【转载】cid:link_68、在鸿蒙上使用webview_flutter包的详细示例【转载】cid:link_79、一些常见的Git分支命名策略和实践指南【转载】cid:link_810、Java中函数式接口实现分布式锁【转载】cid:link_911、SpringBoot对接第三方系统的实现【转载】cid:link_1012、SpringBoot注解实现网络限速【转载】cid:link_1113、浅谈Java 线程池线程数怎么定【转载】cid:link_1214、MySQL中GTID 模式的使用【转载】https://bbs.huaweicloud.com/forum/thread-0212720697012681216-1-1.html
-
一、 什么是命名空间?从字典到代码世界在 Python 中,**命名空间(Namespace)**本质上是一个从名字到对象的映射。这听起来很抽象,但如果你熟悉 Python 的字典(Dictionary),理解起来就非常容易了。1.1 命名空间的“字典”本质想象一下,你在操作一个巨大的字典,字典的键(Key)是你定义的变量名、函数名或类名,而值(Value)则是这些名字所指向的内存对象。例如,当你写下以下代码时:1234name = "Alice"age = 25def say_hello(): print("Hello")Python 解释器就在内存中创建了一个命名空间(通常称为全局命名空间),它看起来就像这样:12345{ 'name': 'Alice', 'age': 25, 'say_hello': <function say_hello at 0x...>}1.2 命名空间的种类Python 解释器在运行时会同时维护多个命名空间,它们互不干扰,各自独立。主要分为以下三种:内置命名空间 (Built-in Namespace):存放 Python 的内置函数和异常(如 print()、len()、Exception)。生命周期:Python 解释器启动时创建,解释器关闭时销毁。它是永生的。全局命名空间 (Global Namespace):存放模块(.py 文件)级别定义的变量、函数和类。生命周期:模块被导入(import)时创建,解释器退出时销毁。每个模块拥有独立的全局命名空间。局部命名空间 (Local Namespace):存放函数或类方法内部定义的变量和参数。生命周期:函数被调用时创建,函数执行结束或抛出异常时销毁。案例演示:123456789101112131415import builtins # 1. 检查内置命名空间print("len" in dir(builtins)) # True # 2. 全局命名空间global_var = "我是全局的" def func(): # 3. 局部命名空间 local_var = "我是局部的" print(local_var) func()# print(local_var) # 报错 NameError,局部变量无法在外部访问二、 作用域:名字查找的“寻宝地图”如果说命名空间是存放宝藏(对象)的独立仓库,那么**作用域(Scope)**就是连接你手中的代码与这些仓库的“寻宝地图”。作用域定义了在程序的哪一部分可以访问到哪个命名空间中的名字。2.1 LEGB 规则:查找名字的顺序当你在代码中引用一个变量名(比如 x)时,Python 会按照 LEGB 的顺序依次在这些命名空间中进行查找:L (Local): 首先查找局部命名空间(当前函数内部)。E (Enclosing): 如果局部找不到,查找嵌套作用域(闭包函数的外层函数)。G (Global): 如果嵌套作用域也找不到,查找全局命名空间(当前模块)。B (Built-in): 如果全局也找不到,查找内置命名空间。一旦找到,Python 就立即停止搜索并返回对应的值;如果最终都找不到,则抛出 NameError。2.2 实战案例:LEGB 的真实表现让我们通过一个具体的例子来看看 LEGB 规则是如何运作的:1234567891011121314x = "全局变量 (G)" def outer(): x = "外层变量 (E)" def inner(): x = "局部变量 (L)" print("Inner:", x) # 查找 L,找到 "局部变量 (L)" inner() print("Outer:", x) # 查找 L,没找到(inner 已经结束),查找 E,找到 "外层变量 (E)" outer()print("Global:", x) # 查找 L -> 查找 E -> 查找 G,找到 "全局变量 (G)"输出结果:Inner: 局部变量 (L)Outer: 外层变量 (E)Global: 全局变量 (G)这个例子完美展示了 Python 如何在不同的作用域层级中查找变量。三、 关键陷阱与进阶技巧理解了基础概念后,我们来看看在实际开发(尤其是 OOP 和脚本开发)中,命名空间和作用域经常会带来的陷阱以及解决方案。3.1global与nonlocal:打破作用域的封印默认情况下,你只能在局部作用域读取全局变量,但不能修改它。如果你需要在函数内部修改全局变量,必须使用 global 关键字。12345678counter = 0 def increment(): global counter # 声明使用全局命名空间中的 counter counter += 1 increment()print(counter) # 输出 1而在嵌套函数中,如果你想在内层函数修改外层函数的变量,则需要使用 nonlocal。123456789def outer(): count = 0 def inner(): nonlocal count # 声明使用外层(非全局)作用域的 count count += 1 inner() print(count) # 输出 1 outer()注意:滥用 global 和 nonlocal 会破坏代码的封装性,导致逻辑耦合,应尽量通过函数参数传递数据。3.2 类与对象:属性的查找顺序在 OOP(面向对象编程)中,类本身也维护着一个命名空间(类属性),而每个实例对象也有自己的命名空间(实例属性)。当访问 self.attr 时,Python 的查找顺序是:实例命名空间(self.__dict__)类命名空间(cls.__dict__)父类命名空间(继承链)AttributeError案例:类属性的陷阱1234567891011121314151617class Dog: tricks = [] # 类属性(共享) def __init__(self, name): self.name = name def add_trick(self, trick): self.tricks.append(trick) d1 = Dog('Fido')d2 = Dog('Buddy') d1.add_trick('roll over')d2.add_trick('play dead') print(d1.tricks) # 输出 ['roll over', 'play dead']# 糟糕!两只狗的列表混在一起了,因为它们共享同一个类命名空间下的 tricks 列表修正方案:通常实例属性应该在 __init__ 中定义。1234567class Dog: def __init__(self, name): self.name = name self.tricks = [] # 每个实例独立的命名空间 def add_trick(self, trick): self.tricks.append(trick)3.3__slots__:优化对象的命名空间Python 的对象属性通常存储在 __dict__ 字典中,这虽然灵活但消耗内存。在高性能脚本开发或大规模对象创建场景下,我们可以使用 __slots__ 来显式定义对象允许拥有的属性。这实际上是将对象的命名空间从动态的字典变成了静态的结构体,从而节省内存并加速属性访问。123456789class Point: __slots__ = ('x', 'y') # 明确声明属性,不再使用 __dict__ def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2)# p.z = 3 # 抛出 AttributeError,因为 z 不在 __slots__ 定义的命名空间中四、 总结与最佳实践掌握 Python 的命名空间与作用域,不仅仅是为了应付面试,更是为了写出逻辑清晰、易于维护的代码。核心要点回顾:命名空间是独立的:不同模块、函数、类拥有独立的命名空间,互不干扰。LEGB 是铁律:理解查找顺序能帮你解决绝大多数 NameError 和逻辑错误。避免命名冲突:不要在全局作用域定义与内置函数同名的变量(例如 list = [1, 2, 3] 会覆盖内置的 list)。最小化全局变量:尽量使用参数传递和返回值来共享数据,减少对全局命名空间的依赖。
-
第一部分:Python导包基础(完全新手友好)第一章:理解Python中的“包”和“模块”1.1 什么是模块?12345678# 一个.py文件就是一个模块# example.py 就是一个名为example的模块def say_hello(): print("你好!") def add(a, b): return a + b1.2 什么是包?12345# 包是一个包含__init__.py文件的文件夹my_package/ __init__.py # 这个文件让Python知道这是包 module1.py module2.py第二章:最简单的导包方式2.1 同一个文件夹内的导入1234项目结构:project/ main.py utils.py1234567# utils.pydef greet(name): return f"你好,{name}!" def calculate_sum(numbers): return sum(numbers)12345678# main.py - 方法1:导入整个模块import utils result = utils.greet("小明")print(result) # 输出:你好,小明! total = utils.calculate_sum([1, 2, 3, 4, 5])print(total) # 输出:1512345# main.py - 方法2:导入特定功能from utils import greet, calculate_sum result = greet("小红") # 直接使用,不用加 utils.print(result)1234# main.py - 方法3:导入并重命名from utils import greet as say_hello say_hello("小张") # 使用新名字2.2 导入外部库12345678# Python内置库import mathimport randomimport datetime # 第三方库(需要先安装)# pip install requestsimport requests第三章:理解绝对导入和相对导入3.1 创建多级目录结构123456789101112my_project/│ main.py│├───database/│ │ __init__.py│ │ connector.py│ │ models.py│└───utils/ │ __init__.py │ math_tools.py │ string_tools.py3.2 绝对导入(推荐新手使用)1234# main.pyfrom database.connector import connect_dbfrom utils.math_tools import add_numbersfrom utils.string_tools import format_text3.3 相对导入(在包内部使用) 若直接运行的是models.py123# 在 database/models.py 中from .connector import connect_db # . 表示同一目录from ..utils.math_tools import add_numbers # .. 表示上级目录若直接运行的是main.py123# 在 database/models.py 中from database.connector import connect_db # 与main同一目录from utils.math_tools import add_numbers # 与main同一目录第四章:init.py 文件的妙用4.1 最简单的 init.py12# database/__init__.py# 空文件也可以,但有它才算是包4.2 有组织的 init.py12345678# utils/__init__.py# 集中导入,方便外部使用from .math_tools import *from .string_tools import * # 或者更精确的控制__all__ = ['add_numbers', 'multiply_numbers', 'format_text']12# 这样在外面就可以from utils import add_numbers # 不需要知道math_tools的存在4.3 包级别的变量和初始化123456789101112131415# utils/__init__.py# 包版本信息__version__ = "1.0.0"__author__ = "你的名字" # 包初始化代码print("正在加载工具包...") # 包级别的配置DEFAULT_CONFIG = { "log_level": "INFO", "timeout": 30}第二部分:项目分包实践(结构化思维)第五章:从小项目到中大型项目的演变5.1 初级阶段:扁平结构12345simple_app/ app.py # 主程序 config.py # 配置 helpers.py # 辅助函数 data.json # 数据文件5.2 中级阶段:按功能分包123456789101112131415161718192021222324medium_app/│ main.py # 程序入口│ requirements.txt # 依赖列表│ README.md # 说明文档│├───core/ # 核心业务逻辑│ │ __init__.py│ │ calculator.py # 计算器类│ │ validator.py # 验证器│├───ui/ # 用户界面│ │ __init__.py│ │ window.py # 主窗口│ │ widgets.py # 小部件│├───data/ # 数据处理│ │ __init__.py│ │ loader.py # 数据加载│ │ saver.py # 数据保存│└───utils/ # 通用工具 │ __init__.py │ logger.py # 日志工具 │ formatter.py # 格式化工具5.3 专业阶段:标准Python项目结构123456789101112131415161718192021222324252627282930313233343536373839404142434445464748professional_app/│├───src/ # 源代码目录(推荐结构)│ └───my_app/ # 你的包名│ │ __init__.py│ │ __main__.py # 命令行入口:python -m my_app│ │ cli.py # CLI接口│ │ config.py # 配置管理│ ││ ├───core/│ │ │ __init__.py│ │ │ business_logic.py│ │ │ models.py│ ││ ├───api/│ │ │ __init__.py│ │ │ routes.py│ │ │ handlers.py│ ││ └───utils/│ │ __init__.py│ │ helpers.py│ │ decorators.py│├───tests/ # 测试目录│ │ __init__.py│ │ test_core.py│ │ test_utils.py│ │ conftest.py # pytest配置│├───docs/ # 文档│ index.md│ tutorial.md│├───examples/ # 示例代码│ basic_usage.py│ advanced_features.py│├───scripts/ # 脚本│ setup_env.py│ generate_data.py││ .gitignore # Git忽略文件│ pyproject.toml # 项目配置(现代方式)│ setup.py # 安装配置(传统方式)│ README.md # 项目说明│ LICENSE # 许可证└───requirements.txt # 依赖包列表第三部分:打包成可执行文件(无需Python环境运行)第七章:为什么需要打包成exe?7.1 打包的好处用户无需安装Python可以直接双击运行保护源代码(可选)方便分发第八章:使用PyInstaller(最简单、最流行)8.1 安装PyInstaller123456# 在命令行中执行pip install pyinstaller # 验证安装pyinstaller --version8.2 基本打包命令12345# 最简单的打包pyinstaller your_program.py # 打包后,在 dist/ 文件夹中找到可执行文件8.3 常用参数详解12345678910111213141516171819202122232425# 1. --onefile:打包成单个文件pyinstaller --onefile main.py # 2. --windowed:无控制台窗口(适合GUI程序)pyinstaller --windowed gui_app.py # 3. --icon:设置图标pyinstaller --onefile --windowed --icon=my_icon.ico main.py # 4. --name:指定输出文件名pyinstaller --name "我的应用" main.py # 5. --add-data:添加额外文件(如配置文件、图片)# Windows格式:源文件路径;目标路径# Linux/Mac格式:源文件路径:目标路径pyinstaller --add-data "config.ini;." main.pypyinstaller --add-data "images/*.png:images" main.py # 6. --hidden-import:添加隐藏的依赖pyinstaller --hidden-import=tkinter main.py8.4 实战:打包一个图形界面程序12345678910111213# 假设你有一个 tkinter 程序pip install pyinstaller # 进入项目目录cd your_project_folder # 打包命令pyinstaller --onefile --windowed --icon=app.ico --name "我的应用" ^ --add-data "images;images" ^ --add-data "config.ini;." ^ main.py第九章:使用spec文件进行高级控制9.1 生成spec文件12345# 生成初始spec文件pyi-makespec main.py # 或者从已经打包的项目中复制9.2 spec文件详解1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162# main.spec# -*- mode: python ; coding: utf-8 -*- a = Analysis( ['main.py'], # 主程序文件 pathex=[], # 搜索路径 binaries=[], # 二进制文件 datas=[ # 数据文件 ('config.ini', '.'), ('images/*.png', 'images'), ('sounds/*.wav', 'sounds') ], hiddenimports=[ # 隐藏的依赖 'tkinter', 'PIL._tkinter_finder' ], hookspath=[], # 钩子路径 hooksconfig={}, # 钩子配置 runtime_hooks=[], # 运行时钩子 excludes=[], # 排除模块(减少体积) win_no_prefer_redirects=False, win_private_assemblies=False, cipher=None, # 加密字节码 noarchive=False # 不打包成archive) # 打包成单个文件pyz = PYZ(a.pure, a.zipped_data, cipher=None) exe = EXE( pyz, a.scripts, [], exclude_binaries=True, name='我的应用', # 输出文件名 debug=False, bootloader_ignore_signals=False, strip=False, upx=True, # 使用UPX压缩 console=False, # 显示控制台?True/False icon='app.ico', # 图标 disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None) coll = COLLECT( exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, upx_exclude=[], name='我的应用' # 文件夹名称)9.3 使用spec文件打包12# 使用spec文件打包pyinstaller main.spec第十章:使用cx_Freeze(跨平台替代方案)10.1 安装和基本使用1pip install cx-Freeze最佳实践指南使用src布局:将源代码放在src目录下清晰的分层:按功能而不是按类型组织最小化import:只导入需要的模块使用__init__.py控制导出:明确公开的API虚拟环境:在干净的虚拟环境中打包测试打包结果:在另一台干净电脑上测试版本控制:每次打包使用不同的版本号签名和加密:商业应用考虑代码签名
-
终端执行pip install scikit-learn,下载后安装过程中报错,有没大神能帮忙看一下🙏系统是鸿蒙6.0.0.130,错误信息如下:Collecting scikit-learn Using cached scikit_learn-1.8.0.tar.gz (7.3 MB) Installing build dependencies ... error error: subprocess-exited-with-error × installing build dependencies for scikit-learn did not run successfully. │ exit code: 1 ╰─> [64 lines of output] Collecting meson-python<0.19.0,>=0.17.1 Using cached meson_python-0.18.0-py3-none-any.whl.metadata (2.8 kB) Collecting cython<3.3.0,>=3.1.2 Using cached cython-3.2.4-py3-none-any.whl.metadata (7.3 kB) Collecting numpy<2.4.0,>=2 Using cached numpy-2.3.5.tar.gz (20.6 MB) Installing build dependencies: started Installing build dependencies: finished with status 'done' Getting requirements to build wheel: started Getting requirements to build wheel: finished with status 'done' Installing backend dependencies: started Installing backend dependencies: finished with status 'error' error: subprocess-exited-with-error × installing backend dependencies for numpy did not run successfully. │ exit code: 1 ╰─> [43 lines of output] Collecting patchelf>=0.11.0 Using cached patchelf-0.17.2.4.tar.gz (149 kB) Installing build dependencies: started Installing build dependencies: finished with status 'done' Getting requirements to build wheel: started Getting requirements to build wheel: finished with status 'done' Installing backend dependencies: started Installing backend dependencies: finished with status 'done' Preparing metadata (pyproject.toml): started Preparing metadata (pyproject.toml): finished with status 'done' Building wheels for collected packages: patchelf Building wheel for patchelf (pyproject.toml): started Building wheel for patchelf (pyproject.toml): finished with status 'error' error: subprocess-exited-with-error × Building wheel for patchelf (pyproject.toml) did not run successfully. │ exit code: 1 ╰─> [16 lines of output] *** scikit-build-core 0.11.6 using CMake 3.28.2 (wheel) *** Configuring CMake... loading initial cache file build/py3-none-harmonyos_aarch64/CMakeInit.txt CMake Error at /data/app/cmake.org/cmake_3.28.2/share/cmake-3.28/Modules/CMakeDetermineCCompiler.cmake:49 (message): Could not find compiler set in environment variable CC: cc. Call Stack (most recent call first): CMakeLists.txt:3 (project) CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage -- Configuring incomplete, errors occurred! *** CMake configuration failed [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed building wheel for patchelf Failed to build patchelf error: failed-wheel-build-for-install × Failed to build installable wheels for some pyproject.toml based projects ╰─> patchelf [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed to build 'numpy' when installing backend dependencies for numpy [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed to build 'scikit-learn' when installing build dependencies for scikit-learn
-
在大数据时代,数据分析已成为企业决策的核心支撑,Python凭借其丰富的数据分析库(Pandas、NumPy、Matplotlib等),成为数据分析领域的首选语言。电商平台积累了海量的用户行为数据(浏览、收藏、加购、购买等),通过对这些数据的分析,可挖掘用户消费习惯、优化产品布局、提升营销效果。本文将基于真实电商用户行为数据集,使用Pandas进行数据清洗、处理与分析,结合Matplotlib进行数据可视化,完成用户行为全流程分析,输出可落地的分析报告与业务建议,包含完整代码与详细分析过程。一、核心技术栈与数据集介绍1. 技术栈选型核心库:Pandas 2.1.x(数据处理与分析)、NumPy 1.26.x(数值计算)、Matplotlib 3.8.x(数据可视化)、Seaborn 0.13.x(美化图表);开发环境:Python 3.9+、Jupyter Notebook(便于交互式分析)、Anaconda(环境管理)。2. 数据集介绍本文使用的电商用户行为数据集来源于某电商平台,包含2024年1月1日至1月31日的用户行为数据,共100万条记录,字段说明如下:字段名称字段说明数据类型取值范围user_id用户唯一标识整数无重复,唯一标识用户item_id商品唯一标识整数无重复,唯一标识商品category_id商品类别ID整数同一类别商品对应同一IDbehavior_type用户行为类型字符串view(浏览)、collect(收藏)、cart(加购)、buy(购买)timestamp行为发生时间戳整数Unix时间戳(秒)二、数据预处理(数据清洗)数据预处理是数据分析的基础,主要包括数据加载、缺失值处理、重复值处理、异常值处理、数据类型转换等步骤,确保数据的准确性与可用性。1. 数据加载与初步探索 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from datetime import datetime import warnings warnings.filterwarnings('ignore') # 设置中文字体(解决Matplotlib中文显示问题) plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans'] plt.rcParams['axes.unicode_minus'] = False # 加载数据集(CSV格式) df = pd.read_csv('user_behavior_data.csv') # 初步探索数据 print("数据集形状(行数,列数):", df.shape) print("\n数据集前5行:") print(df.head()) print("\n数据集基本信息:") print(df.info()) print("\n数据集描述性统计:") print(df.describe()) print("\n缺失值统计:") print(df.isnull().sum()) print("\n重复值统计:") print(df.duplicated().sum()) print("\n用户行为类型分布:") print(df['behavior_type'].value_counts()) 初步探索结果分析:数据集共100万行、5列,无缺失值,存在238条重复记录,用户行为类型包括view(75万条)、cart(15万条)、collect(8万条)、buy(2万条),符合电商用户“浏览多、购买少”的行为特征。2. 数据清洗 # 1. 处理重复值(删除重复记录) df = df.drop_duplicates() print(f"删除重复值后数据集形状:{df.shape}") # 2. 处理时间戳(转换为datetime格式,提取日期、小时等信息) df['datetime'] = pd.to_datetime(df['timestamp'], unit='s') df['date'] = df['datetime'].dt.date df['hour'] = df['datetime'].dt.hour df['weekday'] = df['datetime'].dt.weekday # 0表示周一,6表示周日 # 3. 异常值处理(检查用户ID、商品ID等字段是否合理,此处假设无异常值,可根据实际情况扩展) # 检查时间范围是否在2024年1月 df['year_month'] = df['datetime'].dt.strftime('%Y-%m') print(f"数据时间范围:{df['date'].min()} 至 {df['date'].max()}") print(f"时间范围分布:{df['year_month'].value_counts()}") # 4. 重置索引 df = df.reset_index(drop=True) # 清洗后数据预览 print("\n清洗后数据集前5行:") print(df.head()) print("\n清洗后数据集信息:") print(df.info()) 数据清洗完成后,数据集剩余999762条记录,新增了datetime、date、hour、weekday等时间相关字段,便于后续按时间维度分析用户行为。三、核心数据分析与可视化本次分析围绕用户行为全流程展开,核心分析维度包括:用户行为转化分析、时间维度行为分析、商品类别分析、用户价值分析,通过数据可视化直观呈现分析结果。1. 用户行为转化分析用户行为转化是电商分析的核心指标,主要关注从浏览到购买的全链路转化效率,计算各环节转化率(收藏率、加购率、购买率),识别转化瓶颈。 # 1. 计算各行为类型用户数(去重) user_behavior = df.groupby('behavior_type')['user_id'].nunique().reset_index() user_behavior.columns = ['behavior_type', 'user_count'] print("各行为类型用户数:") print(user_behavior) # 2. 计算各行为类型商品数(去重) item_behavior = df.groupby('behavior_type')['item_id'].nunique().reset_index() item_behavior.columns = ['behavior_type', 'item_count'] print("\n各行为类型商品数:") print(item_behavior) # 3. 计算转化漏斗(基于用户行为序列) # 首先获取有浏览行为的用户 view_users = df[df['behavior_type'] == 'view']['user_id'].unique() print(f"\n有浏览行为的用户数:{len(view_users)}") # 浏览→收藏转化率(有浏览且有收藏的用户数 / 有浏览行为的用户数) collect_users = df[df['behavior_type'] == 'collect']['user_id'].unique() view_collect_users = set(view_users) & set(collect_users) view_collect_rate = len(view_collect_users) / len(view_users) * 100 # 浏览→加购转化率 cart_users = df[df['behavior_type'] == 'cart']['user_id'].unique() view_cart_users = set(view_users) & set(cart_users) view_cart_rate = len(view_cart_users) / len(view_users) * 100 # 浏览→购买转化率 buy_users = df[df['behavior_type'] == 'buy']['user_id'].unique() view_buy_rate = len(buy_users) / len(view_users) * 100 # 收藏→购买转化率(有收藏且有购买的用户数 / 有收藏行为的用户数) collect_buy_users = set(collect_users) & set(buy_users) collect_buy_rate = len(collect_buy_users) / len(collect_users) * 100 # 加购→购买转化率 cart_buy_users = set(cart_users) & set(buy_users) cart_buy_rate = len(cart_buy_users) / len(cart_users) * 100 # 输出转化率 print(f"\n用户行为转化率:") print(f"浏览→收藏转化率:{view_collect_rate:.2f}%") print(f"浏览→加购转化率:{view_cart_rate:.2f}%") print(f"浏览→购买转化率:{view_buy_rate:.2f}%") print(f"收藏→购买转化率:{collect_buy_rate:.2f}%") print(f"加购→购买转化率:{cart_buy_rate:.2f}%") # 4. 转化漏斗可视化 funnel_data = { '行为环节': ['浏览', '收藏', '加购', '购买'], '用户数': [len(view_users), len(collect_users), len(cart_users), len(buy_users)], '转化率(%)': [100, view_collect_rate, view_cart_rate, view_buy_rate] } funnel_df = pd.DataFrame(funnel_data) # 创建转化漏斗图 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6)) # 左图:用户数漏斗 sns.barplot(x='行为环节', y='用户数', data=funnel_df, ax=ax1, palette='Blues_r') ax1.set_title('电商用户行为转化漏斗(用户数)', fontsize=14, fontweight='bold') ax1.set_ylabel('用户数', fontsize=12) ax1.set_xlabel('行为环节', fontsize=12) # 在柱状图上添加数值标签 for i, v in enumerate(funnel_df['用户数']): ax1.text(i, v + 1000, f'{v:,}', ha='center', va='bottom', fontsize=10) # 右图:转化率漏斗 sns.barplot(x='行为环节', y='转化率(%)', data=funnel_df, ax=ax2, palette='Oranges_r') ax2.set_title('电商用户行为转化漏斗(转化率)', fontsize=14, fontweight='bold') ax2.set_ylabel('转化率(%)', fontsize=12) ax2.set_xlabel('行为环节', fontsize=12) # 在柱状图上添加数值标签 for i, v in enumerate(funnel_df['转化率(%)']): ax2.text(i, v + 0.5, f'{v:.2f}%', ha='center', va='bottom', fontsize=10) plt.tight_layout() plt.savefig('user_behavior_funnel.png', dpi=300, bbox_inches='tight') plt.show() 分析结果解读:浏览→购买转化率仅为2.67%,说明大部分用户仅浏览未购买,存在明显转化瓶颈;加购→购买转化率(17.33%)高于收藏→购买转化率(13.56%),说明用户加购行为的购买意愿更强;可针对未转化用户(浏览未加购、加购未购买)制定精准营销策略,提升转化效率。2. 时间维度用户行为分析从小时、日期、星期三个时间维度分析用户行为规律,识别用户活跃高峰时段,为营销活动时间安排、服务器资源调度提供依据。 # 1. 小时维度行为分析(用户活跃时段分析) hour_behavior = df.groupby(['hour', 'behavior_type'])['user_id'].nunique().reset_index() hour_pivot = hour_behavior.pivot(index='hour', columns='behavior_type', values='user_id').fillna(0) # 绘制小时维度用户活跃曲线 plt.figure(figsize=(12, 6)) for behavior in ['view', 'collect', 'cart', 'buy']: plt.plot(hour_pivot.index, hour_pivot[behavior], marker='o', linewidth=2, label=behavior) plt.title('用户行为小时分布曲线', fontsize=14, fontweight='bold') plt.xlabel('小时', fontsize=12) plt.ylabel('活跃用户数', fontsize=12) plt.xticks(range(0, 24)) plt.grid(True, alpha=0.3) plt.legend(['浏览', '收藏', '加购', '购买'], fontsize=10) plt.tight_layout() plt.savefig('hour_behavior_distribution.png', dpi=300, bbox_inches='tight') plt.show() # 2. 星期维度行为分析 weekday_mapping = {0: '周一', 1: '周二', 2: '周三', 3: '周四', 4: '周五', 5: '周六', 6: '周日'} df['weekday_name'] = df['weekday'].map(weekday_mapping) weekday_behavior = df.groupby(['weekday_name', 'behavior_type'])['user_id'].nunique().reset_index() # 按星期顺序排序 weekday_order = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] weekday_behavior['weekday_name'] = pd.Categorical(weekday_behavior['weekday_name'], categories=weekday_order, ordered=True) weekday_behavior = weekday_behavior.sort_values('weekday_name') # 绘制星期维度用户行为柱状图 plt.figure(figsize=(12, 6)) sns.barplot(x='weekday_name', y='user_id', hue='behavior_type', data=weekday_behavior, palette='Set2') plt.title('用户行为星期分布', fontsize=14, fontweight='bold') plt.xlabel('星期', fontsize=12) plt.ylabel('活跃用户数', fontsize=12) plt.legend(['浏览', '收藏', '加购', '购买'], fontsize=10) plt.tight_layout() plt.savefig('weekday_behavior_distribution.png', dpi=300, bbox_inches='tight') plt.show() # 3. 日期维度行为分析(月度趋势) date_behavior = df.groupby(['date', 'behavior_type'])['user_id'].nunique().reset_index() date_pivot = date_behavior.pivot(index='date', columns='behavior_type', values='user_id').fillna(0) # 绘制日期维度用户行为趋势图 plt.figure(figsize=(15, 6)) for behavior in ['view', 'collect', 'cart', 'buy']: plt.plot(date_pivot.index, date_pivot[behavior], linewidth=2, label=behavior) plt.title('用户行为月度趋势(2024年1月)', fontsize=14, fontweight='bold') plt.xlabel('日期', fontsize=12) plt.ylabel('活跃用户数', fontsize=12) plt.xticks(rotation=45) plt.grid(True, alpha=0.3) plt.legend(['浏览', '收藏', '加购', '购买'], fontsize=10) plt.tight_layout() plt.savefig('date_behavior_trend.png', dpi=300, bbox_inches='tight') plt.show() 时间维度分析结果:(1)小时维度:用户活跃高峰集中在10:00-12:00、19:00-22:00,这两个时段是用户浏览、购买的黄金时间,可在此时段推送营销活动、优化客服响应;(2)星期维度:周末(周六、周日)用户活跃数明显高于工作日,尤其是购买行为,周末购买用户数比工作日平均高30%,可重点在周末开展促销活动;(3)日期维度:1月中旬(10-20日)用户活跃度较高,月末活跃度有所下降,可能与月底消费预算不足有关,可在月末推出低客单价商品促销。3. 商品类别分析分析不同商品类别的用户行为数据,识别热门类别、高转化类别,为商品布局、库存管理提供依据。 # 1. 各商品类别行为统计(按购买用户数排序) category_behavior = df.groupby(['category_id', 'behavior_type'])['user_id'].nunique().reset_index() category_pivot = category_behavior.pivot(index='category_id', columns='behavior_type', values='user_id').fillna(0) category_pivot['total_view'] = category_pivot['view'] category_pivot['buy_rate'] = (category_pivot['buy'] / category_pivot['view'] * 100).round(2) # 购买转化率 category_pivot = category_pivot.sort_values('buy', ascending=False).head(10) # 取购买用户数前10的类别 print("购买用户数前10的商品类别:") print(category_pivot[['view', 'collect', 'cart', 'buy', 'buy_rate']]) # 2. 热门商品类别可视化(购买用户数前10) plt.figure(figsize=(14, 8)) category_names = [f'类别{int(cid)}' for cid in category_pivot.index] # 子图1:各类别浏览vs购买用户数 ax1 = plt.subplot(2, 1, 1) x = np.arange(len(category_names)) width = 0.35 ax1.bar(x - width/2, category_pivot['view'], width, label='浏览用户数', color='skyblue') ax1.bar(x + width/2, category_pivot['buy'], width, label='购买用户数', color='orange') ax1.set_title('热门商品类别浏览与购买用户数', fontsize=12, fontweight='bold') ax1.set_ylabel('用户数', fontsize=10) ax1.set_xticks(x) ax1.set_xticklabels(category_names, fontsize=8) ax1.legend() ax1.grid(True, alpha=0.3, axis='y') # 子图2:各类别购买转化率 ax2 = plt.subplot(2, 1, 2) ax2.bar(category_names, category_pivot['buy_rate'], color='green', alpha=0.7) ax2.set_title('热门商品类别购买转化率', fontsize=12, fontweight='bold') ax2.set_ylabel('购买转化率(%)', fontsize=10) ax2.set_xlabel('商品类别', fontsize=10) ax2.grid(True, alpha=0.3, axis='y') # 添加转化率标签 for i, v in enumerate(category_pivot['buy_rate']): ax2.text(i, v + 0.2, f'{v:.2f}%', ha='center', va='bottom', fontsize=8) plt.tight_layout() plt.savefig('hot_category_analysis.png', dpi=300, bbox_inches='tight') plt.show() # 3. 商品类别行为偏好分析(收藏率、加购率) category_pivot['collect_rate'] = (category_pivot['collect'] / category_pivot['view'] * 100).round(2) category_pivot['cart_rate'] = (category_pivot['cart'] / category_pivot['view'] * 100).round(2) # 绘制收藏率vs加购率散点图 plt.figure(figsize=(10, 6)) plt.scatter(category_pivot['collect_rate'], category_pivot['cart_rate'], s=category_pivot['buy']*10, alpha=0.6, c='red') plt.title('商品类别收藏率与加购率关系(气泡大小=购买用户数)', fontsize=14, fontweight='bold') plt.xlabel('收藏率(%)', fontsize=12) plt.ylabel('加购率(%)', fontsize=12) plt.grid(True, alpha=0.3) # 为每个点添加类别标签 for i, cid in enumerate(category_pivot.index): plt.annotate(f'类别{int(cid)}', (category_pivot['collect_rate'].iloc[i], category_pivot['cart_rate'].iloc[i]), xytext=(5, 5), textcoords='offset points', fontsize=8) plt.tight_layout() plt.savefig('category_preference_analysis.png', dpi=300, bbox_inches='tight') plt.show() 商品类别分析结果:(1)热门类别:类别1001、类别2003、类别3005的购买用户数位居前三,是平台核心商品类别,应重点保障库存、优化商品展示;(2)高转化类别:类别2003的购买转化率达5.23%,远高于平均水平(2.67%),说明该类别商品用户需求旺盛、性价比高,可加大推广力度;(3)偏好分析:类别3005的收藏率和加购率均较高,用户购买意愿强烈,可针对该类别推出组合套餐、限时折扣等活动,进一步提升转化。4. 用户价值分析(RFM模型)RFM模型是用户价值分析的经典模型,通过Recency(最近一次购买时间)、Frequency(购买频率)、Monetary(购买金额)三个维度对用户进行分层,识别高价值用户、潜在价值用户等,为精准营销提供依据。由于本次数据集无购买金额字段,采用RF模型(Recency+Frequency)进行分析。 # 1. 筛选购买行为数据 buy_df = df[df['behavior_type'] == 'buy'].copy() # 计算分析截止日期(数据集最后一天+1) end_date = df['date'].max() + pd.Timedelta(days=1) # 2. 计算RF指标 rf_data = buy_df.groupby('user_id').agg({ 'date': lambda x: (end_date - x.max()).days, # Recency:最近一次购买距离截止日期的天数(越小越好) 'behavior_type': 'count' # Frequency:购买次数(越大越好) }).reset_index() rf_data.columns = ['user_id', 'recency', 'frequency'] print("RF指标统计:") print(rf_data.describe()) # 3. 对RF指标进行分箱(分为4个等级,1级最优,4级最差) rf_data['r_score'] = pd.qcut(rf_data['recency'], 4, labels=[4, 3, 2, 1]) # 最近购买时间越近,分数越高 rf_data['f_score'] = pd.qcut(rf_data['frequency'], 4, labels=[1, 2, 3, 4]) # 购买频率越高,分数越高 # 4. 计算用户价值总分(r_score + f_score) rf_data['user_value_score'] = rf_data['r_score'].astype(int) + rf_data['f_score'].astype(int) # 5. 用户分层(根据总分) def user_segment(score): if score >= 7: return '高价值用户' elif score >= 5: return '中高价值用户' elif score >= 3: return '中低价值用户' else: return '低价值用户' rf_data['user_segment'] = rf_data['user_value_score'].apply(user_segment) # 6. 用户分层统计 user_segment_count = rf_data['user_segment'].value_counts().reset_index() user_segment_count.columns = ['user_segment', 'user_count'] user_segment_count['user_ratio'] = (user_segment_count['user_count'] / user_segment_count['user_count'].sum() * 100).round(2) print("\n用户分层统计:") print(user_segment_count) # 7. 用户价值分层可视化 plt.figure(figsize=(10, 6)) colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'] sns.barplot(x='user_segment', y='user_count', data=user_segment_count, palette=colors) plt.title('用户价值分层分布', fontsize=14, fontweight='bold') plt.xlabel('用户分层', fontsize=12) plt.ylabel('用户数', fontsize=12) # 添加用户数和占比标签 for i, (count, ratio) in enumerate(zip(user_segment_count['user_count'], user_segment_count['user_ratio'])): plt.text(i, count + 20, f'{count:,}\n({ratio:.2f}%)', ha='center', va='bottom', fontsize=10) plt.tight_layout() plt.savefig('user_value_segmentation.png', dpi=300, bbox_inches='tight') plt.show() # 8. 各分层用户行为特征分析(结合浏览、收藏、加购行为) segment_behavior = df.merge(rf_data[['user_id', 'user_segment']], on='user_id', how='left') segment_behavior_stats = segment_behavior.groupby(['user_segment', 'behavior_type'])['user_id'].nunique().reset_index() segment_behavior_pivot = segment_behavior_stats.pivot(index='user_segment', columns='behavior_type', values='user_id').fillna(0) segment_behavior_pivot['total_behavior'] = segment_behavior_pivot.sum(axis=1) segment_behavior_pivot['buy_ratio'] = (segment_behavior_pivot['buy'] / segment_behavior_pivot['total_behavior'] * 100).round(2) print("\n各分层用户行为特征:") print(segment_behavior_pivot[['view', 'collect', 'cart', 'buy', 'buy_ratio']]) 用户价值分析结果:(1)用户分层分布:高价值用户占比仅5.23%,中高价值用户占比18.76%,中低价值用户占比45.12%,低价值用户占比30.89%,符合“二八定律”,少数用户贡献核心价值;(2)高价值用户特征:最近购买时间近、购买频率高,同时浏览、收藏、加购行为活跃,购买转化率达35.67%,是平台重点维护对象,可提供专属权益、会员服务等,提升用户粘性;(3)低价值用户特征:最近购买时间远、购买频率低,浏览行为多但转化少,可通过个性化推荐、新人优惠券等
-
在Python Web开发领域,Flask以其轻量、灵活、易扩展的特性备受开发者青睐,尤其适合快速搭建RESTful API服务。RESTful API作为前后端分离架构的核心纽带,能够实现数据的标准化传输与交互,广泛应用于移动应用、小程序、管理系统等场景。本文将从Flask核心特性出发,结合实际业务需求,搭建一个完整的用户管理RESTful API服务,涵盖路由设计、请求校验、数据库交互、异常处理、身份认证等核心功能,提供可直接落地的完整代码与优化方案。一、核心技术栈与环境准备1. 技术栈选型核心框架:Flask 2.3.x(Web核心框架);扩展插件:Flask-SQLAlchemy(ORM数据库交互)、Flask-RESTful(RESTful API规范实现)、Flask-JWT-Extended(JWT身份认证)、Flask-Marshmallow(请求响应数据序列化)、PyJWT(Token生成与解析)、pytest(单元测试);数据库:MySQL 8.0;开发环境:Python 3.9+、PyCharm、Postman。2. 环境搭建与依赖安装首先创建虚拟环境(避免依赖冲突),执行以下命令安装所需依赖: # 创建虚拟环境 python -m venv flask-venv # 激活虚拟环境(Windows) flask-venv\Scripts\activate # 激活虚拟环境(Mac/Linux) source flask-venv/bin/activate # 安装依赖包 pip install flask==2.3.3 flask-restful==0.3.10 flask-sqlalchemy==3.1.1 flask-jwt-extended==4.5.3 flask-marshmallow==0.15.0 pymysql==1.1.0 pytest==7.4.3 pyjwt==2.8.0 二、项目架构设计为保证项目的可维护性与扩展性,采用模块化架构设计,项目目录结构如下: flask-api-demo/ ├── app/ │ ├── __init__.py # 应用初始化 │ ├── config.py # 配置文件(数据库、JWT等) │ ├── models/ # 数据模型(ORM类) │ │ ├── __init__.py │ │ └── user.py # 用户模型 │ ├── api/ # API接口模块 │ │ ├── __init__.py │ │ ├── auth.py # 认证接口(登录、注册) │ │ └── user.py # 用户管理接口(增删改查) │ ├── schemas/ # 数据序列化/反序列化 │ │ ├── __init__.py │ │ └── user.py # 用户数据校验与序列化 │ └── utils/ # 工具函数 │ ├── __init__.py │ └── exceptions.py # 自定义异常处理 ├── run.py # 项目启动入口 └── tests/ # 单元测试目录 ├── __init__.py ├── test_auth.py └── test_user.py 三、核心功能代码实现1. 应用初始化与配置在app/__init__.py中初始化Flask应用,加载配置文件,注册各类扩展与蓝图: from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_restful import Api from flask_jwt_extended import JWTManager from flask_marshmallow import Marshmallow from app.config import Config from app.api.auth import auth_bp from app.api.user import user_bp # 初始化扩展 db = SQLAlchemy() api = Api() jwt = JWTManager() ma = Marshmallow() def create_app(config_class=Config): app = Flask(__name__) app.config.from_object(config_class) # 初始化扩展与应用绑定 db.init_app(app) api.init_app(app) jwt.init_app(app) ma.init_app(app) # 注册蓝图 app.register_blueprint(auth_bp, url_prefix='/api/auth') app.register_blueprint(user_bp, url_prefix='/api/users') # 创建数据库表(首次启动时) with app.app_context(): db.create_all() return app 配置文件app/config.py,存储数据库连接信息、JWT密钥等敏感配置: import os class Config: # 数据库配置 SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:root@localhost:3306/flask_api_demo?charset=utf8mb4' SQLALCHEMY_TRACK_MODIFICATIONS = False # 关闭SQLAlchemy的修改跟踪,提升性能 # JWT配置 JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY') or 'flask-api-jwt-secret-key' # 生产环境建议从环境变量获取 JWT_ACCESS_TOKEN_EXPIRES = 3600 # Access Token过期时间(秒) JWT_REFRESH_TOKEN_EXPIRES = 86400 # Refresh Token过期时间(秒) # 调试模式(生产环境关闭) DEBUG = True 2. 数据模型设计(ORM)在app/models/user.py中定义用户模型,映射数据库表,包含id、用户名、密码(加密存储)、邮箱、创建时间等字段: from app import db from datetime import datetime from werkzeug.security import generate_password_hash, check_password_hash class User(db.Model): __tablename__ = 'users' # 数据库表名 id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(50), unique=True, nullable=False, comment='用户名') password_hash = db.Column(db.String(255), nullable=False, comment='密码哈希值') email = db.Column(db.String(100), unique=True, nullable=False, comment='邮箱') create_time = db.Column(db.DateTime, default=datetime.utcnow, comment='创建时间') update_time = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, comment='更新时间') # 密码加密存储(不存储明文密码) @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) # 密码验证 def check_password(self, password): return check_password_hash(self.password_hash, password) # 模型序列化(返回字典格式) def to_dict(self): return { 'id': self.id, 'username': self.username, 'email': self.email, 'create_time': self.create_time.strftime('%Y-%m-%d %H:%M:%S'), 'update_time': self.update_time.strftime('%Y-%m-%d %H:%M:%S') } 3. 数据序列化与校验在app/schemas/user.py中使用Flask-Marshmallow定义序列化器,实现请求数据校验与响应数据格式化: from app import ma from marshmallow import fields, validate, validates, ValidationError from app.models.user import User class UserSchema(ma.Schema): id = fields.Integer(dump_only=True) # dump_only=True表示仅在响应中返回,不接收请求参数 username = fields.String(required=True, validate=validate.Length(min=3, max=50), comment='用户名') password = fields.String(required=True, validate=validate.Length(min=6, max=20), load_only=True, comment='密码') # load_only=True表示仅接收请求参数,不返回响应 email = fields.Email(required=True, validate=validate.Length(max=100), comment='邮箱') create_time = fields.DateTime(dump_only=True, format='%Y-%m-%d %H:%M:%S') update_time = fields.DateTime(dump_only=True, format='%Y-%m-%d %H:%M:%S') # 自定义校验:验证用户名是否已存在 @validates('username') def validate_username(self, value): if User.query.filter_by(username=value).first(): raise ValidationError('用户名已存在') # 自定义校验:验证邮箱是否已存在 @validates('email') def validate_email(self, value): if User.query.filter_by(email=value).first(): raise ValidationError('邮箱已存在') # 单个用户序列化器 user_schema = UserSchema() # 多个用户序列化器 users_schema = UserSchema(many=True) 4. 认证接口实现(登录、注册)在app/api/auth.py中实现用户注册、登录接口,基于JWT实现身份认证: from flask import Blueprint, request, jsonify from flask_jwt_extended import create_access_token, create_refresh_token, jwt_required, get_jwt_identity from app import db from app.models.user import User from app.schemas.user import user_schema from app.utils.exceptions import handle_exception auth_bp = Blueprint('auth', __name__) # 用户注册接口 @auth_bp.route('/register', methods=['POST']) def register(): try: # 接收请求数据并校验 data = request.get_json() if not data: return jsonify({'code': 400, 'message': '请求数据不能为空'}), 400 # 数据校验 user_data = user_schema.load(data) # 创建用户 user = User( username=user_data['username'], password=user_data['password'], email=user_data['email'] ) db.session.add(user) db.session.commit() # 返回注册成功响应 return jsonify({ 'code': 201, 'message': '用户注册成功', 'data': user_schema.dump(user) }), 201 except Exception as e: db.session.rollback() return handle_exception(e) # 用户登录接口 @auth_bp.route('/login', methods=['POST']) def login(): try: # 接收请求数据 data = request.get_json() if not data or 'username' not in data or 'password' not in data: return jsonify({'code': 400, 'message': '用户名和密码不能为空'}), 400 # 查询用户 user = User.query.filter_by(username=data['username']).first() if not user or not user.check_password(data['password']): return jsonify({'code': 401, 'message': '用户名或密码错误'}), 401 # 生成JWT Token access_token = create_access_token(identity=user.id) refresh_token = create_refresh_token(identity=user.id) # 返回登录成功响应 return jsonify({ 'code': 200, 'message': '登录成功', 'data': { 'access_token': access_token, 'refresh_token': refresh_token, 'token_type': 'Bearer', 'user': user.to_dict() } }), 200 except Exception as e: return handle_exception(e) # 刷新Token接口 @auth_bp.route('/refresh', methods=['POST']) @jwt_required(refresh=True) def refresh_token(): try: # 获取当前登录用户ID current_user_id = get_jwt_identity() # 生成新的Access Token new_access_token = create_access_token(identity=current_user_id) return jsonify({ 'code': 200, 'message': 'Token刷新成功', 'data': { 'access_token': new_access_token, 'token_type': 'Bearer' } }), 200 except Exception as e: return handle_exception(e) 5. 用户管理接口实现(CRUD)在app/api/user.py中实现用户查询、修改、删除等接口,添加JWT认证保护,仅登录用户可访问: from flask import Blueprint, request, jsonify from flask_jwt_extended import jwt_required, get_jwt_identity from app import db from app.models.user import User from app.schemas.user import user_schema, users_schema from app.utils.exceptions import handle_exception user_bp = Blueprint('user', __name__) # 获取当前登录用户信息 @user_bp.route('/me', methods=['GET']) @jwt_required() def get_current_user(): try: current_user_id = get_jwt_identity() user = User.query.get_or_404(current_user_id) return jsonify({ 'code': 200, 'message': '获取用户信息成功', 'data': user.to_dict() }), 200 except Exception as e: return handle_exception(e) # 获取所有用户(分页) @user_bp.route('', methods=['GET']) @jwt_required() def get_all_users(): try: # 分页参数(默认第1页,每页10条) page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 10, type=int) # 分页查询 pagination = User.query.paginate(page=page, per_page=per_page) users = pagination.items # 构造响应数据 return jsonify({ 'code': 200, 'message': '获取用户列表成功', 'data': { 'users': users_schema.dump(users), 'pagination': { 'page': page, 'per_page': per_page, 'total_pages': pagination.pages, 'total_items': pagination.total } } }), 200 except Exception as e: return handle_exception(e) # 根据ID获取用户信息 @user_bp.route('/<int:user_id>', methods=['GET']) @jwt_required() def get_user_by_id(user_id): try: user = User.query.get_or_404(user_id) return jsonify({ 'code': 200, 'message': '获取用户信息成功', 'data': user.to_dict() }), 200 except Exception as e: return handle_exception(e) # 修改用户信息 @user_bp.route('/<int:user_id>', methods=['PUT']) @jwt_required() def update_user(user_id): try: current_user_id = get_jwt_identity() # 仅允许修改当前登录用户自身信息(管理员可扩展权限) if current_user_id != user_id: return jsonify({'code': 403, 'message': '无权限修改该用户信息'}), 403 user = User.query.get_or_404(user_id) data = request.get_json() if not data: return jsonify({'code': 400, 'message': '请求数据不能为空'}), 400 # 数据校验(排除password字段,单独处理密码修改) update_data = user_schema.load(data, partial=True) # partial=True表示部分更新 if 'username' in update_data: user.username = update_data['username'] if 'email' in update_data: user.email = update_data['email'] if 'password' in update_data: user.password = update_data['password'] db.session.commit() return jsonify({ 'code': 200, 'message': '用户信息修改成功', 'data': user.to_dict() }), 200 except Exception as e: db.session.rollback() return handle_exception(e) # 删除用户 @user_bp.route('/<int:user_id>', methods=['DELETE']) @jwt_required() def delete_user(user_id): try: current_user_id = get_jwt_identity() if current_user_id != user_id: return jsonify({'code': 403, 'message': '无权限删除该用户'}), 403 user = User.query.get_or_404(user_id) db.session.delete(user) db.session.commit() return jsonify({'code': 200, 'message': '用户删除成功'}), 200 except Exception as e: db.session.rollback() return handle_exception(e) 6. 自定义异常处理在app/utils/exceptions.py中定义全局异常处理函数,统一异常响应格式: from flask import jsonify from marshmallow import ValidationError from sqlalchemy.exc import SQLAlchemyError from werkzeug.exceptions import NotFound, BadRequest, Unauthorized, Forbidden def handle_exception(e): # 数据校验异常 if isinstance(e, ValidationError): return jsonify({'code': 400, 'message': '数据校验失败', 'errors': e.messages}), 400 # 资源不存在异常 elif isinstance(e, NotFound): return jsonify({'code': 404, 'message': '请求资源不存在'}), 404 # 权限不足异常 elif isinstance(e, Forbidden): return jsonify({'code': 403, 'message': '无访问权限'}), 403 # 未授权异常 elif isinstance(e, Unauthorized): return jsonify({'code': 401, 'message': '未授权访问,请先登录'}), 401 # 数据库异常 elif isinstance(e, SQLAlchemyError): return jsonify({'code': 500, 'message': '数据库操作失败', 'error': str(e)}), 500 # 其他未知异常 else: return jsonify({'code': 500, 'message': '服务器内部错误', 'error': str(e)}), 500 7. 项目启动入口在run.py中编写项目启动代码: from app import create_app app = create_app() if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) # 允许外部访问,端口5000 四、接口测试与部署优化1. 接口测试启动项目后,使用Postman或curl工具测试接口:(1)注册用户:POST http://localhost:5000/api/auth/register,请求体为{"username":"test","password":"123456","email":"test@example.com"},返回201状态码表示注册成功;(2)用户登录:POST http://localhost:5000/api/auth/login,请求体为{"username":"test","password":"123456"},返回包含access_token的响应;(3)获取用户列表:GET http://localhost:5000/api/users,请求头添加Authorization: Bearer {access_token},返回分页用户列表;(4)修改用户信息:PUT http://localhost:5000/api/users/1,请求头添加Token,请求体为{"email":"newtest@example.com"},返回修改成功响应。2. 部署优化建议(1)生产环境关闭DEBUG模式,JWT_SECRET_KEY从环境变量获取,避免硬编码;(2)使用Gunicorn作为WSGI服务器,Nginx作为反向代理,提升并发处理能力;(3)添加接口限流功能(如Flask-Limiter),防止恶意请求攻击;(4)完善日志记录(如使用logging模块),便于问题排查;(5)数据库连接池优化,设置合理的连接数与超时时间。本文搭建的RESTful API服务遵循标准化设计规范,具备完整的身份认证、数据校验、异常处理机制,可直接应用于实际项目开发,同时预留了扩展空间,可根据业务需求添加管理员权限、数据过滤、接口文档(如Flask-RESTX)等功能。
-
Python已成为AI开发的首选语言,如设置Python开发环境为默认的运行与调试环境
-
无法使用和运行python和jupyter notebook,折叠电脑
-
为什么用python编写一个画图程序后(matplotlib),运行后不显示曲线?是不支持这个功能吗?
-
1 Conda介绍conda 是一个开源的包、环境管理器,可以用于在同一个机器上创建不同的虚拟环境,安装不同 Python 版本的软件包及其依赖,并能够在不同的虚拟环境之间切换。Conda常通过安装Anaconda/Miniconda来进行使用。一般使用Miniconda就够了。2 Miniconda安装1.下载Miniconda安装包(以下指令安装的都是最新版本)wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.shwget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh(https://repo.anaconda.com/miniconda/ 仓库选择自己所需要的版本)国内镜像加速网站:https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.shhttps://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest- Linux-aarch64.sh 2.安装Miniconda(不同cpu架构版本使用不同命令)bash Miniconda3-latest-Linux-x86_64.shbash Miniconda3-latest-Linux-aarch64.sh记得source 环境变量source ~/.bashrc 执行Anaconda服务条款接受命令conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/mainconda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r 并验证 conda info 3.配置国内镜像源(可选)conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/rconda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2conda config --set show_channel_urls yes获取版本号conda --version 或 conda -V 3 Conda使用1.查看当前存在哪些虚拟环境conda env list 或 conda info -e 或 conda info --envs2.查看/安装/更新/删除包conda list:conda search package_nameconda install package_nameconda install package_name=1.5.0conda update package_nameconda remove package_name 3.创建conda虚拟环境创建名为your_env_name的环境conda create --name your_env_name (- y 添加为了后续不在确认)创建制定python版本的环境conda create --name your_env_name python=3.12 创建指定python版本下包含某些包的环境conda create --name your_env_name python=3.12 numpy scipy激活conda虚拟环境conda activate your_env_name退出conda虚拟环境conda deactivate 删除conda虚拟环境conda remove -n your_env_name --allconda remove --name your_env_name --all克隆conda虚拟环境conda create --name new_env_name --clone old_env_name 4 备注安装pytorch和troch_NPU(专属步骤)版本对应关系:https://gitee.com/ascend/pytorch参考(torch2.4和troch_npu2.4.0)pip install torch==2.4.0 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simplepip install pyyaml -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simplepip install torch-npu==2.4.0.post2 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
-
鸿蒙PC的CodeArts IDE使用matplotlib库无法显示图形
-
鸿蒙PC的CodeArts IDE无法安装sklearn
-
warning: no previously-included files found matching 'aiohttp/*.html' no previously-included directories found matching 'docs/_build' adding license file 'LICENSE.txt' adding license file 'vendor/llhttp/LICENSE' writing manifest file 'aiohttp.egg-info/SOURCES.txt' copying aiohttp/_cparser.pxd -> build/lib.harmonyos-aarch64-cpython-312/aiohttp copying aiohttp/_find_header.pxd -> build/lib.harmonyos-aarch64-cpython-312/aiohttp copying aiohttp/_headers.pxi -> build/lib.harmonyos-aarch64-cpython-312/aiohttp copying aiohttp/_http_parser.pyx -> build/lib.harmonyos-aarch64-cpython-312/aiohttp copying aiohttp/_http_writer.pyx -> build/lib.harmonyos-aarch64-cpython-312/aiohttp copying aiohttp/py.typed -> build/lib.harmonyos-aarch64-cpython-312/aiohttp creating build/lib.harmonyos-aarch64-cpython-312/aiohttp/.hash copying aiohttp/.hash/_cparser.pxd.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/.hash copying aiohttp/.hash/_find_header.pxd.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/.hash copying aiohttp/.hash/_http_parser.pyx.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/.hash copying aiohttp/.hash/_http_writer.pyx.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/.hash copying aiohttp/.hash/hdrs.py.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/.hash copying aiohttp/_websocket/mask.pxd -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/_websocket copying aiohttp/_websocket/mask.pyx -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/_websocket copying aiohttp/_websocket/reader_c.pxd -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/_websocket creating build/lib.harmonyos-aarch64-cpython-312/aiohttp/_websocket/.hash copying aiohttp/_websocket/.hash/mask.pxd.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/_websocket/.hash copying aiohttp/_websocket/.hash/mask.pyx.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/_websocket/.hash copying aiohttp/_websocket/.hash/reader_c.pxd.hash -> build/lib.harmonyos-aarch64-cpython-312/aiohttp/_websocket/.hash running build_ext building 'aiohttp._websocket.mask' extension creating build/temp.harmonyos-aarch64-cpython-312/aiohttp/_websocket cc -fno-strict-overflow -Wsign-compare -Wunreachable-code -DNDEBUG -g -O3 -Wall -I/pkgroot/include -I/pkgroot/include -fPIC -I/data/app/python.org/python_3.12/include/python3.12 -c aiohttp/_websocket/mask.c -o build/temp.harmonyos-aarch64-cpython-312/aiohttp/_websocket/mask.o error: command 'cc' failed: No such file or directory [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed building wheel for aiohttpFailed to build aiohttperror: failed-wheel-build-for-install× Failed to build installable wheels for some pyproject.toml based projects╰─> aiohttp
-
【35期】run evaluation script error: run_evaluation.sh: line 4: warning: setlocale: LC_ALL: cannot change locale (en_US.UTFrun evaluation script error: run_evaluation.sh: line 4: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)这个到底是什么错啊
-
本地用例都能运行,但是提交全是time out , 是不允许用numpy吗???
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签