☰
星空组网+Python实战:在另一台电脑上查看CSV报表
2026/10/4 6:40:09 网站建设 项目流程

🔥承渊政道:个人主页

❄️个人专栏:《C语言基础语法知识》 《数据结构与算法》 《C++知识内容》 《Linux系统与网络知识》 《算法刷题指南》 《测评文章活动推广》 《大模型语言路线学习》 《MySQL数据库学习》 《Python知识内容》 《cpolar知识学习》

✨逆境不吐心中苦,顺境不忘来时路!✨
🎬 博主简介:

项目进度常常先记在一张CSV表里.文件放在Ubuntu上,换到Mac查看时,通常要再复制一份.这次我把CSV做成一个简单的网页:Ubuntu负责读取文件,Mac通过星空组网地址打开报表,文件改完后刷新页面就能看到更新.整个项目只有server.py和report.csv两个文件,使用Python标准库,不安装第三方包.本次使用模拟项目记录,验证范围是Mac到Ubuntu组网地址的访问、文件更新和服务清理.这个网页没有单独的登录鉴权,能够访问该端口的组网成员都可查看内容,适合临时演示.


目录

  • 1.从官网登录入口,确认两台设备在线
  • 2.在Ubuntu检查环境,再创建项目
  • 3.写一个读取CSV的网页服务
  • 4.启动服务,从Mac打开报表
  • 5.修改Ubuntu文件,验证Mac刷新结果
  • 6.打不开或数据不对时,按现象排查
  • 7.验证结束后停止服务,删除演示项目

1.从官网登录入口,确认两台设备在线

打开星空组网官网,进入账号登录页.已有账号可直接登录,没有账号则从页面进入注册流程.下图是本次打开的空白登录表单,未填写账号或密码.


本次浏览器已有后台登录状态,后续沿用该会话.进入后台首页后,“组网状态”显示组网成功、两台设备在线.截图仅保留状态区域,账号信息没有放进配图.


设备列表的入口是“设备管理 → 成员列表”.本次核对了Mac和Ubuntu-Board的虚拟IP,两端客户端均为 6.1.0,分别使用已有成员.按照官方设备与成员管理说明,多台长期在线设备应使用各自的成员账号.客户端还未安装的设备,可以先参考Linux 使用说明或Mac 使用说明完成接入.

设备或配置本次实际值分工
Ubuntu-BoardUbuntu 22.04 LTS,Python 3.10.12保存 CSV,运行网页服务
Ubuntu 组网 IP192.168.188.5服务监听地址
Mac 组网 IP192.168.188.1浏览器访问、刷新验证
网页端口18101本次检查为空闲端口

这些地址来自本次设备,复现时请换成自己的组网IP.浏览器中的地址应指向运行Python服务的 Ubuntu.


2.在Ubuntu检查环境,再创建项目

打开Ubuntu终端,先确认系统、Python、组网网卡地址和端口:

lsb_release-dspython3--versionip-4-briefaddr show StarVPN ss-ltn'( sport = :18101 )'

本次输出是 Ubuntu 22.04 LTS、Python 3.10.12,StarVPN 网卡具有192.168.188.5/24地址。ss只有表头,没有监听记录,说明检查时端口没有被占用.网卡状态中的UNKNOWN要结合地址和实际访问判断.

新建一个独立目录;如果同名目录已经存在,先检查内容,不要覆盖已有文件.

mkdir~/starvpn-csv-report-20261001cd~/starvpn-csv-report-20261001

创建模拟数据文件:

cat>report.csv<<'CSV' 项目,负责人,状态,备注 登录页面,小林,已完成,账号入口已确认 报表接口,小周,进行中,等待页面验收 数据校验,小陈,待开始,"检查中文、逗号" 发布说明,小林,待开始,整理使用步骤 CSV

CSV 第一行是表头.字段里包含英文逗号,时,需要用双引号包住整个字段.程序使用标准库csv.reader解析,并以newline=""打开文件;这些写法可对照Python CSV 文档.


3.写一个读取CSV的网页服务

把以下完整代码保存为同目录的server.py:

importargparseimportcsvimportloggingfromdatetimeimportdatetimefromhtmlimportescapefromhttp.serverimportBaseHTTPRequestHandler,ThreadingHTTPServerfrompathlibimportPath REPORT=Path(__file__).with_name("report.csv")DEFAULT_PORT=18101MAX_FILE_BYTES=64*1024defrender_report(path:Path)->bytes:ifpath.stat().st_size>MAX_FILE_BYTES:raiseValueError("CSV 超过 64 KiB,请先缩小演示数据")withpath.open(encoding="utf-8-sig",newline="")asfile:rows=[rowforrowincsv.reader(file,strict=True)ifrow]ifnotrowsornotany(rows[0]):raiseValueError("CSV 缺少表头")ifany(len(row)!=len(rows[0])forrowinrows[1:]):raiseValueError("CSV 数据行与表头列数不一致")head="".join(f'<th scope="col">{escape(cell)}</th>'forcellinrows[0])body="".join("<tr>"+"".join(f"<td>{escape(cell)}</td>"forcellinrow)+"</tr>"forrowinrows[1:])ifnotbody:body=f'<tr><td colspan="{len(rows[0])}">暂无数据</td></tr>'updated=datetime.fromtimestamp(path.stat().st_mtime).strftime("%Y-%m-%d %H:%M:%S")returnf'''<!doctype html> <html lang="zh-CN"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>项目进度报表</title> <style> body{{margin:0;background:#f4f5f0;color:#24332e;font:16px/1.7 system-ui,sans-serif}} main{{max-width:960px;margin:64px auto;padding:36px;background:white;border:1px solid #dce2da}} header{{display:flex;justify-content:space-between;align-items:center;gap:24px}} h1{{font-size:32px;margin:4px 0 12px}}p{{color:#617168;margin:8px 0}} a{{display:inline-block;padding:10px 20px;background:#245844;color:white;text-decoration:none}} a:focus-visible{{outline:3px solid #f2ac42;outline-offset:4px}} .table-wrap{{overflow:auto;margin:28px 0}}table{{width:100%;border-collapse:collapse;text-align:left}} caption{{text-align:left;font-weight:600;padding-bottom:12px}} th,td{{padding:15px 18px;border-bottom:1px solid #e3e9e1}}th{{background:#edf2eb}} small{{color:#617168}}@media(max-width:640px){{main{{margin:20px;padding:20px}}header{{flex-wrap:wrap}}}} </style> <main> <header><div><small>CSV REPORT / 跨设备查看</small><h1>项目进度报表</h1> <p>刷新页面即可读取 Ubuntu 上的最新文件。</p></div><a href="/">刷新报表</a></header> <p>数据文件:report.csv | 记录数:{len(rows)-1}| 文件更新时间:{updated}</p> <div class="table-wrap"><table><caption>模拟项目记录</caption> <thead><tr>{head}</tr></thead><tbody>{body}</tbody></table></div> <small>演示数据,非真实业务记录。页面仅提供查看。</small> </main></html>'''.encode("utf-8")classHandler(BaseHTTPRequestHandler):defdo_GET(self)->None:ifself.path!="/":self.send_error(404,"Not found")returntry:body=render_report(REPORT)except(OSError,UnicodeError,csv.Error,ValueError):logging.exception("读取 report.csv 失败")self.send_error(500,"Cannot read report.csv; check server log")returnself.send_response(200)self.send_header("Content-Type","text/html; charset=utf-8")self.send_header("Content-Length",str(len(body)))self.send_header("Cache-Control","no-store")self.send_header("X-Content-Type-Options","nosniff")self.end_headers()self.wfile.write(body)defmain()->None:parser=argparse.ArgumentParser(description="临时 CSV 报表页")parser.add_argument("--bind",required=True,help="本机星空组网 IPv4 地址")parser.add_argument("--port",type=int,default=DEFAULT_PORT)args=parser.parse_args()ifnot1<=args.port<=65535:parser.error("端口必须在 1 到 65535 之间")try:withThreadingHTTPServer((args.bind,args.port),Handler)asserver:print(f"报表地址:http://{args.bind}:{args.port}/",flush=True)try:server.serve_forever()exceptKeyboardInterrupt:print("报表服务已停止",flush=True)exceptOSErroraserror:parser.exit(2,f"启动失败:{error}\n")if__name__=="__main__":main()

程序固定读取脚本旁边的report.csv,只开放首页/,没有目录浏览或任意文件下载功能.CSV 按 UTF-8 读取,也兼容带 BOM 的 UTF-8 文件;转成网页前,每个字段经过escape处理.每次请求都会重新读取文件,并返回Cache-Control: no-store.

为了让文件出错时容易排查,程序检查表头和列数,限制演示CSV大小为64KiB.读取失败时,浏览器收到 HTTP 500,具体异常留在Ubuntu终端.只有表头、没有数据的文件会显示“暂无数据”.

保存后核对两个文件,并检查 Python 语法:

ls-lhserver.py report.csv python3-c"import ast; from pathlib import Path; ast.parse(Path('server.py').read_text()); print('Python syntax: OK')"catreport.csv


4.启动服务,从Mac打开报表

在 Ubuntu 的项目目录里运行:

python3 server.py--bind192.168.188.5--port18101

出现报表地址:http://192.168.188.5:18101/后,保持终端运行.这里使用 Ubuntu 自己的组网 IP 作为监听地址.本次没有修改防火墙配置.

在已经接入同一组网的Mac 上,可以先用命令检查 HTTP 响应:

curl--noproxy'*'--max-time5-f-o/dev/null-w'HTTP %{http_code}\n'http://192.168.188.5:18101/

本次返回HTTP200,Ubuntu 终端也记录了来自Mac组网地址192.168.188.1的请求.

接着在 Mac 浏览器中输入http://192.168.188.5:18101/.初版页面显示4条记录,“报表接口”一行的状态为“进行中”,备注为“等待页面验收”.中文内容也能正常显示.


5.修改Ubuntu文件,验证Mac刷新结果

另开一个 Ubuntu 终端,进入同一目录,修改模拟记录并查看文件:

cd~/starvpn-csv-report-20261001sed-i's/报表接口,小周,进行中,等待页面验收/报表接口,小周,已完成,Mac 访问验证通过/'report.csvcatreport.csv ss-ltn'( sport = :18101 )'

这条sed命令只针对本文给出的模拟行.处理自己的CSV时,建议直接编辑文件或使用CSV读写工具,避免误替换其他记录.

下面的终端截图显示,文件中的状态已变为“已完成”,服务仍在192.168.188.5:18101上监听.查看ss时应读Local Address:Port列,右侧的Peer Address:Port不是服务的监听地址.

回到Mac,点击“刷新报表”.同一行显示“已完成”,备注变为“Mac访问验证通过”,页面的文件更新时间也随之变化.本次更新过程中没有重启 Python 服务.


补充验证中,带双引号的字段正常解析,HTML特殊字符经过转义.访问/report.csv、/server.py和其他未开放路径均返回 404.临时移走CSV后首页返回500,恢复文件后重新返回 200.


6.打不开或数据不对时,按现象排查

现象检查位置
浏览器连接失败两台客户端是否在线;地址是否为 Ubuntu 组网 IP;启动终端是否还在运行;ss是否有目标端口监听
启动时报地址错误--bind是否填写了本机已有地址;网卡名称和 IP 以实际输出为准
启动时报端口占用先查明现有进程;为演示换一个空闲端口,不要直接结束其他服务
首页返回 500查看 Ubuntu 异常日志,检查文件存在、编码、CSV 引号和每行列数
刷新后内容没有变化确认改的是server.py同目录的report.csv,再点击“刷新报表”

如果服务已监听但连接仍失败,再检查设备防火墙和组网访问策略.需要调整规则时,仅放行访问端到目标端口,不要直接关闭防火墙.


7.验证结束后停止服务,删除演示项目

回到运行Python的Ubuntu终端,按Ctrl+C.程序输出“报表服务已停止”.再检查端口,并只删除这次创建的两个文件和空目录:

ss-ltn'( sport = :18101 )'cd~rm-- ~/starvpn-csv-report-20261001/server.py ~/starvpn-csv-report-20261001/report.csvrmdir~/starvpn-csv-report-20261001test!-e~/starvpn-csv-report-20261001&&printf'Project directory removed\n'

删除前请确认目录里只有本次演示文件.本次清理后,ss没有端口监听记录,项目目录已不存在;Mac 再次请求同一地址时连接失败,curl退出码为 7.


🚀真正的勇者不是流泪的人,而是含泪奔跑的人!

敬请期待下一篇文章内容


每日心灵鸡汤: 真正高级的人生,是懂得给自己留白!

留白不只是一种高级的审美,也是一种很稀缺的能力.很多人总想把话说尽、把空间占满、把关系抓紧、把人生安排得滴水不漏、把交易账户始终塞满仓位,本质上是无法忍受空白与不确定.真正有分寸的人,反而知道什么时候该停,什么不必解释,什么不必拥有.留白的本质,不是空,而是克制;不是缺少,而是知道什么可以不要.

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询