算法测试平台是专为验证、评估和优化算法设计的综合性工具或系统,广泛应用于机器学习、数据分析、人工智能等领域。其核心目标在于提升算法开发效率、确保结果可靠性,并支持团队协作,本文将搭建简易的算法平台,提供简单的实现方式(与实际项目有很大的不同),但实现思路是清晰的。
一、基本环境搭建
1、环境配置
以下配置适用于团队协作、持续集成(CI/CD)和中等并发测试任务(如数百个测试用例),能够满足在 Ubuntu 上搭建基于 Django + Docker + MySQL 的算法自动化测试平台。
Ubuntu版本:20.04
配置信息:8核CPU、16G内存、100G系统盘、500G硬盘
2、NFS系统搭建
NFS(Network File System,网络文件系统) 是一种分布式文件系统协议,允许客户端通过网络访问远程服务器上的文件和目录,就像访问本地存储一样。它在 Unix/Linux 系统中广泛应用,尤其在分布式计算、集群管理和跨平台文件共享中扮演重要角色。
搭建文档:Ubuntu搭建nfs网络文件系统_ubuntu 网络文件系统-CSDN博客
挂载时需要注意:
服务器未启用 NFSv4协议,改用默认版本:
mount -t nfs IP地址:/data /root/test
启用时(一般为启用) ,使用NFSv4协议:
mount -t nfs4 IP地址:/data /root/test
而不指定版本直接输入以下指令,则nfs协议版本除了取决于服务器版本,还取决于mount的客户端版本,即可能是nfs4也可能是nfs,设置对于一些mount版本,即使强制指定nfs,实际挂载后也会是nfs4:
mount IP地址:/data /root/test
总之,客户端版本指定的nfs协议要与服务端一致才能正常连接,否则报错:mount: mounting **:/data on /root/test failed: Connection refused 。
查看已挂载的nfs版本:
mount | grep "/root/test"
卸载已挂载的磁盘:
umount 挂载的目录
3、python3环境(3.13.2)
一般默认安装python3:
一般不装pip:
根据提示安装:
apt install python3-pip
最后发现pip与pip3都指向同一版本路径:
root@localhost:/# pip -V pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8) root@localhost:/# pip3 -V pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8) root@localhost:/#
这个不用管,pip和pip3指向同一程序是 Ubuntu 的默认行为(优先支持 Python 3),后面统一用pip3执行包的安装。
这里我们需要处理一下,安装高一级的python版本,需要安装conda来管理,本文使用python 3.13.2 。
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.shbash Miniconda3-latest-Linux-x86_64.shsource ~/miniconda3/bin/activate # 进入默认的激活环境conda --version # 查看 Conda 版本python --version # 查看 Python 版本(默认安装的是 Python 3.12+)mkdir -p /data/pythons/3.13.2 # 创建3.13.2虚拟环境文件夹conda create --prefix "/data/pythons/3.13.2/env" python==3.13.2 -c conda-forge # 创建3.13.2虚拟环境conda activate /data/pythons/3.13.2/env # 激活/切换环境
4、ssh服务器
搭建文档:Ubuntu能够ping通,但不能ssh登录_能ping通ubuntu无法ssh登录-CSDN博客
5、远程开发环境(可选且推荐)
通过ssh实现,要求Ubuntu上启用ssh服务,如果用pycharm作为开发工具,则要求为专业版才能安装插件。操作步骤:
打开 PyCharm → File → Settings → Project: <项目名> → Python Interpreter。
点击齿轮图标 → Add New Interpreter → SSH Interpreter(需要专业版且安装了插件才显示)。
输入 Ubuntu 的 IP 地址、用户名、密码(或 SSH 密钥)。
路径选择 Ubuntu 上的 Python 可执行文件(如/usr/bin/python3)等。
6、社区开发环境(可选且本文选择)
使用社区版pycharm作为开发工具,只是没有专业版方便,且可能在一些方面不好用,环境搭建可通过以下文档体验。
搭建文档:Django与MySQL实战-CSDN博客
7、git仓库
通过git创建工程,并通过pycharm加载工程。
搭建文档:Pycharm:通过git拉取仓库代码并创建项目环境_pycharm怎么拉取代码-CSDN博客
Ubuntu一般默认安装git,也可通过以下方式安装与配置:
sudo apt updatesudo apt install git # 若已安装,可省略git --versiongit config --global user.name "你的姓名"git config --global user.email "你的邮箱@example.com"git config --listgit initgit clone "仓库地址"git clone "分支"
8、配置conda环境
使用Ancinda3来管理虚拟环境,配置与Ubuntu同版本python,即3.13.2。
搭建文档:Anconda3 的使用_anaconda3-CSDN博客
在pycharm中使用conda环境:
9、django 5.1.3
按照以下步骤创建工程并上传代码到git上。
Ubuntu安装django 5.1.3
conda install django==5.1.3 --channel conda-forge
10、Ubuntu运行服务
在settings文件中设置
ALLOWED_HOSTS = ["服务器本地IP地址"]
运行时使用conda指定的环境运行
python manage.py runserver 0.0.0.0:8000
在电脑上能访问Ubuntu服务即可
11、手动安装mysql 服务(可选,不推荐)
可直接用指令安装,在这里手动自定义安装:
wget https://dev.mysql.com/get/mysql-8.0.33-linux-glibc2.12-x86_64.tar.xzmkdir -p /data/mysqltar -xJvf mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz -C /data/mysqlcd /data/mysqlsudo useradd -r -s /bin/false mysqlsudo ln -s /data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/share/english /data/mysql/sharemysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld --initialize --user=mysql --basedir=/data/mysql --datadir=/data/mysql/data/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysql_ssl_rsa_setup --datadir=/data/mysql/datasudo nano /etc/profile.d/mysql.sh# 添加以下内容:export PATH=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin:$PATHexport LD_LIBRARY_PATH=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/lib:$LD_LIBRARY_PATHsource /etc/profile.d/mysql.shsudo nano /etc/systemd/system/mysql.service# 添加以下内容:[Unit]Description=MySQL Community ServerAfter=network.target[Service]User=mysqlGroup=mysqlExecStart=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld --defaults-file=/etc/my.cnfExecStop=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld_safe --shutdown[Install]WantedBy=multi-user.targetsudo nano /etc/my.cnf# 添加以下内容:[mysqld]datadir=/data/mysql/data# socket=/var/run/mysqld/mysqld.socksocket = ''bind-address = 0.0.0.0pid-file=/var/run/mysqld/mysqld.piduser=mysqlsymbolic-links=0[mysqld_safe]log-error=/var/log/mysqld.logpid-file=/var/run/mysqld/mysqld.pid[client]socket=/var/run/mysqld/mysqld.socksudo mkdir -p /var/run/mysqld sudo chown mysql:mysql /var/run/mysqldsudo chmod 750 /var/run/mysqld# 重新加载 systemd 配置sudo systemctl daemon-reload# 启动并启用服务sudo systemctl start mysqlsudo systemctl enable mysqlsudo systemctl status mysql
设置root无密码登录服务
sudo apt-get updatesudo apt-get install libtinfo5ldconfig -p | grep libtinfosudo systemctl stop mysqlsudo /data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld --skip-grant-tables --user=root &/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysql -u rootFLUSH PRIVILEGES;
创建数据库新用户newuser,mysql密码登录
CREATE USER 'newuser'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';FLUSH PRIVILEGES;ALTER USER 'newuser'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';CREATE USER 'newuser'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%' WITH GRANT OPTION;GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'localhost' WITH GRANT OPTION;FLUSH PRIVILEGES;exit;# 恢复环境ps aux | grep mysql # 查找并杀掉所有进程,再重启服务
创建数据库
CREATE DATABASE algo_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
配置django,首先安装mysqlclient,接着打开settings文件进行配置:
DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", # 使用 MySQL "NAME": "algo_db", # 数据库名 "USER": "newuser", # 数据库用户名 "PASSWORD": "newpassword", # 数据库密码 "HOST": "localhost", # MySQL 服务器地址 "PORT": "3306", # MySQL 端口号 "OPTIONS": { "charset": "utf8mb4", # 兼容 Emoji }, }}
注意,我们要连接的是默认端口3306,而不是支持新协议的33060 (该端口支持MySQL X Protocol新协议):
12、安装docker
安装:
# 卸载旧版本sudo apt-get remove docker docker-engine docker.io containerd.io# 安装必要工具sudo apt-get updatesudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release# 添加官方密钥curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg# 设置docker存储库echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -sc) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# 安装 Docker CE(社区版)sudo apt-get updatesudo apt-get install docker-ce docker-ce-cli containerd.io# 验证sudo docker run hello-world# 输出 "Hello from Docker!" 表示安装成功# 安装 Docker Composesudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composesudo chmod +x /usr/local/bin/docker-composesudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose# 配置非rootsudo usermod -aG docker $USERnewgrp # 使配置立即生效# 开机自启sudo systemctl enable dockersudo systemctl start docker
配置:
sudo mkdir -p /data/docker_appssudo chown -R 999:999 /data/docker_apps # Docker 默认用户和组sudo chmod -R 755 /data/docker_appssudo systemctl stop docker# 移动原有数据到新目录sudo rsync -av /var/lib/docker/ /data/docker_apps/# 编辑 /etc/docker/daemon.json{ "data-root": "/data/docker_apps"}# 重启sudo systemctl start dockersudo systemctl enable docker# 验证# 查看 Docker 数据根目录sudo docker info | grep "Docker Root Dir"
13、使用docker安装mysql服务 (推荐)
sudo mkdir -p /data/docker_apps/mysql/{conf,sock,data}sudo chown -R 999:999 /data/docker_apps/mysql/ # Docker 用户和组sudo chmod -R 755 /data/docker_apps/mysql/cd /data/docker_apps/mysql# 创建文件docker-compose.yml,写入version: '3'services: mysql: image: mysql:8.0 container_name: test_mysql volumes: - /data/docker_apps/mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: newpassword ports: - "3306:3306"# 启动sudo docker-compose up -d# 使用root登录sudo docker exec -it test_mysql mysql -uroot -pnewpasswordCREATE DATABASE IF NOT EXISTS algo_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;CREATE USER 'newuser'@'%' IDENTIFIED BY 'newpassword';CREATE USER 'newuser'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';FLUSH PRIVILEGES;CREATE USER 'newuser'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';FLUSH PRIVILEGES;GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%' WITH GRANT OPTION;GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'localhost' WITH GRANT OPTION;FLUSH PRIVILEGES;
14、django mydql库的选择
优先选择mysqlclient,这也是官方推荐,备选pymysql 。
| 特性 | PyMySQL | mysqlclient (MySQLdb) |
|---|---|---|
| 实现方式 | 纯 Python 实现 | C 语言实现 |
| 安装难度 | 依赖少,pip install pymysql 即可 |
依赖 MySQL 开发库,安装可能较复杂 |
| 性能 | 稍慢(因纯 Python 实现) | 更快(因 C 语言实现) |
| 兼容性 | 兼容 MySQL 8.0(支持 caching_sha2_password) |
旧版本可能不支持 MySQL 8.0 认证方式 |
| Python 版本支持 | Python 3.x | 主要支持 Python 3.x |
| 维护情况 | 仍在积极维护 | 维护较少,较老的 MySQLdb 的封装 |
| 使用方式 | 兼容 MySQLdb API,可替代 mysqlclient |
传统 MySQLdb 接口 |
| django使用方式 | # 强制使用,需要在setting文件中显示调用,配置与mysqlclient 一致。
|
默认使用,安装即可 |
mysqlclient安装比较麻烦,在Ubuntu上安装不完整,通常会报以下错误:
django.db.utils.OperationalError: (2059, "Authentication plugin 'mysql_native_password' cannot be loaded: /data/pythons/3.13.2/env/lib/plugin/mysql_native_password.so: cannot open shared object file: No such file or directory") 在Ubuntu上安装mysqlclient时,务必按照官方文档进行安装:mysqlclient · PyPI
安装GUI:
SSHFS-Win-Manager :Release v1.3.1 · evsar3/sshfs-win-manager (github.com)
挂载服务器成功:
15、SSHFS
winfsp/sshfs-win: SSHFS For Windows (github.com)
二、设计思路参考
1、需要具备的知识
django开发系列文章:Django让web开发更简单(一):运行MVT设计模式_note that only django core commands are listed as -CSDN博客
html学习:
HTML 简介 | 菜鸟教程 (runoob.com)
CSS学习:
CSS 教程 | 菜鸟教程 (runoob.com)
django模板(不推荐但本文使用):
Django 模板 | 菜鸟教程 (runoob.com)
如果前端用的VUE(推荐,但本文不使用),需要学习系列文章:
Vue 3:玩一下web前端技术(一)_web vue3-CSDN博客
本文会给个开发思路,但不深入技术细节与具体实现。
2、网页布局
base.html
{% load static %}<html lang="zh-CN"><head> <meta charset="UTF-8"> <title>定制布局</title> <style> * { margin: 0; padding: 0; box-sizing: border-box } .container { display: grid; grid-template-columns: 20% 80%; min-height: 100vh; } .sidebar { background-color: #333; color: white; padding: 15px; } .right-section { display: grid; grid-template-rows: 10% 90%; height: 100%; } .header-bar { background-color: #4CAF50; color: white; padding: 10px; text-align: center; } .content-area { padding: 20px; background-color: #f5f5f5; } </style></head><body> <div > <!-- 左侧菜单栏 --> <div > <h3>导航菜单</h3> <ul> <li><a href="#">首页</a></li> <li><a href="#">关于我们</a></li> <li><a href="#">服务</a></li> <li><a href="#">联系</a></li> </ul> </div> <!-- 右侧内容区 --> <div > <!-- 顶部信息栏 --> <div > 当前用户:{{ user.username }} <span >2025-03-07 18:22:28</span> </div> <!-- 主要内容区域 --> <div > {% block content %} <p>这里是主要内容区域...</p> {% endblock %} </div> </div> </div></body></html>
index.html
{% extends "base.html" %}{% block title %}首页 - Algorithm Testing Platform{% endblock %}{% block content %} <h1>欢迎来到算法测试平台!</h1> <p>这里是平台的主页内容...</p>{% endblock %}
这样出来的效果是这样:
基于这段代码,可以继续优化,如:将css抽离、所有html继承base.html、继续微调页面布局等。涉及到的django 模板方法粗略汇总如下:
| 类别 | 名称 | 使用示例 | 作用说明 |
|---|---|---|---|
| HTML 标签 | div |
<div >...</div> |
容器元素,用于布局分组 |
ul/li |
<ul><li><a href="#"></a></li></ul> |
创建水平导航菜单 | |
a |
<a href="#">首页</a> |
创建超链接 | |
h3 |
<h3>导航菜单</h3> |
标题标签,显示侧边栏标题 | |
span |
<span >...</span> |
行内元素,用于右对齐时间信息 | |
p |
<p>这里是主要内容区域...</p> |
段落文本显示 | |
| Django 模板方法 | {% load static %} |
{% load static %} |
加载静态文件(CSS/JS)的预处理指令 |
{{ user.username }} |
当前用户:{{ user.username }} |
输出用户对象的username属性值 |
|
{% block content %} |
{% block content %}<p>...</p>{% endblock %} |
定义模板继承的内容区块,子模板可覆盖此部分 |
(1)html继承
{% extends "base.html" %}
(2)块覆盖
父:<title>{% block title %}定制布局{% endblock %}</title>子:{% block title %}首页 - Algorithm Testing Platform{% endblock %}
如:title使用了块{% block %},这样子页就会覆盖父页的对应内容,这跟内容覆盖是同理的。
(3)将css代码注释掉,用标签link代替
<link rel="stylesheet" href="{% static 'css/base.css' %}">
(4)常用CSS属性
| 属性 | 参数类型 | 示例用法 | 效果描述 |
|---|---|---|---|
| width | 长度值、百分比 | width: 200px; | 设置元素的宽度为200像素。 |
| height | 长度值、百分比 | height: 100px; | 设置元素的高度为100像素。 |
| background-color | 颜色值 | background-color: #FF0000; | 设置元素的背景颜色为红色。 |
| color | 颜色值 | color: blue; | 设置文本颜色为蓝色。 |
| margin | 长度值、百分比、关键字 | margin: 10px 5px 10px 5px; | 设置元素的上、右、下、左外边距分别为10px、5px、10px、5px。 |
| padding | 长度值、百分比 | padding: 20px; | 设置元素的内边距为20像素。 |
| border | 长度值、样式、颜色 | border: 1px solid black; | 设置元素的边框为1像素宽、实线、黑色。 |
| font-size | 长度值、百分比、关键字 | font-size: 16px; | 设置字体大小为16像素。 |
| text-align | 关键字 | text-align: center; | 设置文本水平居中对齐。 |
| display | 关键字 | display: flex; | 将元素设置为弹性盒模型布局。 |
| position | 关键字 | position: absolute; | 将元素设置为绝对定位,相对于最近的已定位祖先元素定位。 |
| top | 长度值、百分比 | top: 50px; | 对于绝对定位或固定定位的元素,设置其上边缘距离包含块上边缘的距离为50像素。 |
| left | 长度值、百分比 | left: 100px; | 对于绝对定位或固定定位的元素,设置其左边缘距离包含块左边缘的距离为100像素。 |
| float | 关键字 | float: left; | 使元素向左浮动。 |
| z-index | 整数 | z-index: 2; | 设置元素的堆叠顺序,数字越大,元素越在顶部。 |
(5)你可能会遇到的问题
调节前端交互还是需要点经验的,可能需要有点耐心;
一些CSS属性可能在特定情况下不生效,得了解其运行逻辑才能用的起来;
页面不适配的情况在一些情况下会暴露出来,经验不足时不好处理;
django模板继承可能会出现一些情况;
......
(6)前端框架与UI组件
可以考虑前后端分离,如:
简介 | Vue.js (vuejs.org)
Container 布局容器 | Element Plus (element-plus.org)
可以考虑基于CSS的UI组件(本文采用),如:
Bootstrap · 世界上最流行的HTML, CSS, 和JS框架www.bootstrapcn.net
通过CDN引入UI组件:
CDN官网查询Bootstrp版本:https://www.jsdelivr.com/?query=bootstrap
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" integrity="sha256-3gQJhtmj7YnV1fmtbVcnAV6eI4ws0Tr48bVZCThtCGQ=" crossorigin="anonymous"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" integrity="sha256-PI8n5gCcz9cQqQXm3PEtDuPG8qx9oFsFctPg0S5zb8g=" crossorigin="anonymous">
3、图片应用
先搭建底层应用,像堆积木一样网上搭建。正常创建与注册应用后,配置一下图片存储目录:
'''配置媒体文件(用于图片上传)'''# settings.pyMEDIA_URL = '/media/'MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
创建模型:
# image_repo/models.pyfrom django.db import modelsclass Image(models.Model): title = models.CharField(max_length=255) description = models.TextField(blank=True) image = models.ImageField(upload_to='images/') # 图片将存储在media/images/目录 uploaded_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title
创建视图:
# image_repo/views.pyfrom django.views.generic import ListView, CreateViewfrom .models import Imageclass ImageView(ListView): model = Image template_name = 'image_repo/image_list.html' context_object_name = 'images'class ImageCreateView(CreateView): model = Image fields = ['title', 'description', 'image'] template_name = 'image_repo/image_form.html'
配置URL:
# image_repo/urls.pyfrom django.urls import pathfrom .views import ImageView, ImageCreateViewurlpatterns = [ path('', ImageView.as_view(), name='image_list'), path('add/', ImageCreateView.as_view(), name='image_add'),]
在主项目的urls.py中包含新应用的URL(省略)
在image_repo/templates/image_repo/创建image_list.html (工程目录结构自行调整):
{% extends "base.html" %}{% block content %}<h2>图片仓库</h2><a href="{% url 'image_add' %}">上传新图片</a><ul> {% for image in images %} <li> <h3>{{ image.title }}</h3> <p>{{ image.description }}</p> <img src="{{ image.image.url }}" width="200" alt="{{ image.title }}"> </li> {% endfor %}</ul>{% endblock %}
创建image_form.html:
{% extends "base.html" %}{% block content %}<h2>上传图片</h2><form method="post" enctype="multipart/form-data"> {% csrf_token %} {{ form.as_p }} <button type="submit">上传</button></form>{% endblock %}
更新网页布局应用(如:core)的侧边栏菜单,关联链接。
修改若干BUG后可实现添加照片和读取照片,需要继续优化,这里省略。
你可能会遇到的问题:
需要配置媒体文件路由;
修改工程目录;
优化界面;
django自带类的学习;
......
4、其他应用
现在图片数据已经有了,剩下的就是如何围绕数据形成业务流的事情了,这里可以采用这样的设计:
测试项目》测试计划》执行测试》测试归档
(1)测试项目
在测试项目中,可以设计测试计划的数据格式,定义参数化图片应用的命令的运行方式。
(2)测试计划
引用测试项目,可添加测试设备、实现与设备的交互,最终生成测试计划。
(3)执行测试
通过测试挂载服务器,获取服务器的图片数据,并通过测试计划的命令执行,最终生成测试结果
(4)测试归档
即将测试归档到指定地方,与测试计划脱钩。
经过这些应用的添加,最终设计出了算法测试平台!麻雀虽小,五脏俱全!希望这些思路能帮助到大家,just do it !
904