写这篇文章之前先说说我怎么碰上a2s的。有段时间我一直在维护一个内部项目的技术文档里面全是靠--、| |手工画的架构图。图是挺直观可放到正式的对外文档里总显得不够体面——像素感太强放大还发虚。手工重绘成矢量图又实在划不来几十张图一张张画下去一天就没了。后来我在找“ASCII 转 SVG”的方案时翻到了a2s试了一下五分钟就把文档里的“豆腐块”全部洗成了清晰可缩放的矢量图那种感觉确实很舒服。这篇文章就围绕a2s的语法、参数和实际应用案例展开。如果你平时写技术文档、画架构图、维护 README或者经常要拿文本形式的信息图去换一种更专业的展示形态那这篇文章应该能帮到你。如果你是刚接触 Python 的新手也没关系下面的内容我会尽量把每一步都拆开讲清楚。1. 认识 a2s它到底解决什么问题1.1 一个拿得出手的场景不少项目里都有这种“手绘”架构图--------------------- --------------------- | Web Server | ---- | Business Core | | | HTTP | | --------------------- --------------------- | | v v --------------------- --------------------- | Cache Cluster | | Database | --------------------- ---------------------这段文本放在代码注释里、放在 README 里都非常直观跨平台也不会丢格式。但一旦你要把它放进 PPT、官网或者正式技术白皮书纯文本的展示就有点单薄了不能无损缩放边框粗细不统一更没法做颜色和样式定制。a2s就是干这件事的。全称是ASCII to SVG本质上是一个字符图形解析器加矢量画布生成器。它把文本里的框线、连接线、字符块识别成对应的几何元素矩形、线段、路径最终输出一份标准 SVG 矢量图。SVG 是纯文本格式的矢量图可以用浏览器直接打开也可以用代码随意改颜色、改线宽还能放进 Word、PPT 和网页里。1.2 它的设计思路a2s的处理流程大致分三步读取文本、识别图形结构、生成 SVG。识别结构这一步是核心它依赖一个字符表a2s.c模块来告诉程序“哪些字符是边框、哪些是线条、哪些是普通文本内容”再通过上下文推断这些字符组成的图形边界。这个思路和直接用 OCR 识别图片完全不一样。OCR 是把光栅图像转成文字和结构a2s是把已经结构化的文本重新解析成几何描述。所以它对输入格式有一定要求——文本中的框线要对齐字符要规整。如果源文件里框线七扭八歪它自然也没办法变出好图来。2. 安装与第一行代码2.1 安装 a2s安装很简单用 pip 就能搞定pip install a2s如果网络环境不太友好可以换国内镜像pip install a2s -i https://pypi.tuna.tsinghua.edu.cn/simple装完之后验证一下python -c import a2s; print(a2s.__version__)能打印出版本号就说明基础环境没问题。注意a2s 依赖 lxml 和 Pillow。如果你用的是非常精简的 Python 环境比如某些 Docker 基础镜像可能需要单独装一下pip install lxml pillow。后面convert_image转 PNG 的时候会用到 Pillow。2.2 第一次转换先准备一个最简单的文本文件input.txt----- | | | 1 | | | -----然后写三行代码import a2s a2s.convert(input.txt, output.svg)打开生成的output.svg你会在浏览器里看到一个规整的矩形中间有个数字1。这个矩形其实是 a2s 识别了-----的边框结构后生成的 SVGrect元素。如果不想指定输出路径a2s 也支持只传源文件a2s.convert(input.txt)不同版本的默认行为可能略有差异有的会生成同名.svg文件有的会把结果直接返回。我的建议是始终显式传第二个参数这样脚本的可控性最强也避免不同环境下的行为差异坑到你。2.3 顺手把 SVG 转成 PNG很多场景下我们不只需要 SVG还需要 PNG 这种位图格式——比如要插入到某些不支持 SVG 的内部 Wiki。a2s 提供了一个配套方法a2s.convert_image(output.svg, output.png)这个方法底层是用 Pillow 把 SVG 渲染成一张 PNG 图片。生成出来的output.png默认会保留透明背景直接放进文档里很干净。3. 核心语法与 API 全解3.1 convert从文本到 SVGconvert是 a2s 最核心的入口。基本签名是a2s.convert(source, targetNone)其中source是输入文件路径target是输出 SVG 文件路径。不传 target 时按默认逻辑处理。实际使用时我更推荐一种写法import a2s result a2s.convert(架构图.txt, 架构图.svg) print(result) # 返回包含转换结果信息的对象从调用方式上可以看出来a2s.convert不直接返回 SVG 字符串它更像个转换驱动器把文件读进来、处理、再把结果写到 target。如果你要在内存里直接拿结果而不落盘一般做法是改用底层模块接口或者先写到临时文件再处理。另外一个使用技巧convert方法处理的是文件不是字符串。如果你手上只有一段已经写好的 ASCII art 字符串可以先把字符串写到临时文件再交给 a2s。虽然多了一步但流程最稳不需要挖底层 API。3.2 convert_image从 SVG 到位图convert_image负责把 SVG 转成 PNG 等位图格式a2s.convert_image(output.svg, output.png)这里有个小细节生成的 PNG 尺寸默认取自 SVG 自身的宽高比例。如果后面发现生成的图片过大或过小不要急着在 a2s 里找缩放参数最通用的做法是转换完成后用 Pillow 二次处理from PIL import Image img Image.open(output.png) img img.resize((600, 400), Image.Resampling.LANCZOS) img.save(resized.png)3.3 命令行方式如果你的工作流里全是 Shell 脚本用命令行更顺手。部分版本安装后会提供命令行入口你可以直接a2s input.txt output.svg如果直接用a2s命令没生效可以用模块方式调用python -m a2s input.txt output.svg具体命令名称在不同分支版本里有一点差别拿不准的时候跑一下--help就知道了。命令行交互适合批量转换做成 Shell 循环一条命令处理一整个目录非常省事。4. 参数模块 tune 详解4.1 为什么需要参数调整ASCII art 里的字符宽度不是统一的。英文小写i和W在大多数等宽字体里宽度一致但如果你用的字体不是严格等宽或者输入文本里混入了全角中文一个汉字约占两个英文字符宽度a2s 在把字符位置换算成 SVG 坐标时就会出现偏差表现成图形错位、框线对不齐。a2s.tune就是用来干“微调”这件事的模块。通过设置参数让解析器知道当前文本使用的是什么样的字符网格从而更准确地映射坐标。4.2 常用参数配置最常见的做法是通过set_params设置全局参数from a2s import tune tune.set_params( doc_w960, # 输出画布宽度 doc_h720, # 输出画布高度 char_w12, # 单个字符宽度 char_h24 # 单个字符高度 )doc_w和doc_h代表最终 SVG 画布的尺寸决定了生成的矢量图整体大小。char_w和char_h则是解析时使用的字符网格尺寸它们影响图形元素的相对坐标。不同版本对参数名可能有一点点兼容差异如果你安装的版本提示参数不识别用下面的方式先看看模块支持什么参数import inspect from a2s import tune print(inspect.signature(tune.set_params))这个方法我在排查参数问题的时候经常用极其灵验。4.3 等宽模式与字符对齐除了set_params还有一个值得单独拎出来讲的是等宽模式。如果你的原始文本里用了大量|、-、来画框线这些字符本身的宽度在常见字体里是一致的但内容部分如果长短不一就会导致整个图形右侧对不齐。a2s 提供类似EqualWidth的开关用来告诉解析器请把所有字符按等宽处理这样框线就能严格对齐。from a2s import tune tune.EqualWidth(True)开启之后解析器会忽略字体本身的度量差异强制把每个字符都放进相同宽度的网格里。这非常适合那些手写规整、刻意对齐过的 ASCII art。但要注意如果你的源文本里混了全角中文强行开启等宽模式反而可能让中文左右产生空隙或不自然拉伸。因为全角汉字天然就是双倍宽度你把它和非等宽字符塞进同一个格子图形是变整齐了可中文字符的观感对不齐了。这种情况下我建议优先保证文本自身严格对齐再用等宽模式微调。4.4 参数选型的几个实操建议我整理了一套在项目里实际用过的参数选择规则直接抄作业也行场景推荐做法纯英文/数字的框线图开启EqualWidth(True)char_w8char_h16含中文注释的架构图关闭等宽开关char_w12char_h24用全角字符对齐要生成高分辨率 PNG不急着调画布先转出 SVG 再二次缩放复杂嵌套框图优先处理源文本对齐不要指望参数能修复错位记住一个原则参数是锦上添花不是雪中送炭。源文本里框线没对齐的话怎么调参数结果都是歪的。5. 实际应用案例5.1 案例一把代码注释里的架构图转成文档素材我在维护一个老项目时发现源码里有一坨架构注释图画的是消息队列的消费链路。这段注释非常清晰但要想放进对外文档就“拿不出手”。我当时做了这几步先把源码注释里的图复制出来保存成queue_arch.txt----------- ----------- ----------- | Producer | topic | Broker | part | Consumer | | P1 | ------- | B1/B2 | ------ | C1 | ----------- ----------- -----------然后执行转换脚本import a2s from a2s import tune # 英文框图开启等宽模式最稳妥 tune.EqualWidth(True) a2s.convert(queue_arch.txt, queue_arch.svg) a2s.convert_image(queue_arch.svg, queue_arch.png)生成的queue_arch.svg直接拖进绘图软件还能继续编辑框、线、文字全部是独立元素。我把文字部分改成品牌色后整张图瞬间就有了“正式文档”的气质。这个场景是我认为 a2s 价值最明显的地方把埋在代码里的图形资产一键“提纯”成可复用素材。5.2 案例二批量转换 docs 目录下的所有文本图后来我发现团队 docs 目录下有一堆.txt架构草图有些还带着版本后缀。人工一个个处理太蠢我就写了个批量脚本import os import a2s from a2s import tune tune.EqualWidth(True) src_dir ./docs/raw dst_dir ./docs/svg os.makedirs(dst_dir, exist_okTrue) for filename in os.listdir(src_dir): if not filename.endswith(.txt): continue src_path os.path.join(src_dir, filename) dst_path os.path.join(dst_dir, filename.replace(.txt, .svg)) try: a2s.convert(src_path, dst_path) print(f[OK] {filename} - {os.path.basename(dst_path)}) except Exception as e: print(f[FAIL] {filename}: {e})这个脚本看起来简单但有几个点我在实际跑的时候才踩到文件名包含中文时个别旧版本在解析路径时可能出问题。给代码开头加上# -*- coding: utf-8 -*-或者统一转成绝对路径再用基本能规避。转换失败不会导致整个脚本崩掉因为包了一层 try/except打日志比中断强。如果某个文件转换后图明显错位我的习惯是先定位源文件是否对齐而不是盲目调参数。批量处理后的所有 SVG 我统一扔进一个assets目录文档需要时直接引用。省下来的时间至少是一下午。5.3 案例三在 Jupyter Notebook 里展示技术图写技术方案的时候我经常用 Jupyter Notebook 做草稿既写思路又贴图。a2s 生成的 SVG 在 Notebook 里展示也很方便import a2s from IPython.display import SVG, display # 先生成 SVG 文件 a2s.convert(design.txt, design.svg) # 再在 Notebook 里渲染出来 display(SVG(filenamedesign.svg))执行完这个单元格生成的架构图会以内联 SVG 的形式直接出现在 Notebook 里。好处是它是矢量图放大不糊而且我可以在同一个 Notebook 里反复修改文本图、重新生成、即时对比。这种“文本改一行图片跟着变”的工作流比打开画图工具改半天高效太多了。如果你还想在 Notebook 里顺手导出 PNG加一行就行a2s.convert_image(design.svg, design.png)Notebook 里可以直接插图片适合最后把方案贴到在线文档的场景。5.4 案例四CI 流水线里自动生成 API 结构图再扩展一步。我们有个服务模块的接口文档是自动生成的里面有一张 API 结构图。以前的流程是开发手画后截图上传经常忘了更新。后来我用 a2s 做了自动化在仓库里维护一个api_structure.txt代码合并时CI 跑一个脚本文件import a2s from a2s import tune tune.EqualWidth(True) a2s.convert(api_structure.txt, public/api-structure.svg) a2s.convert_image(public/api-structure.svg, public/api-structure.png)这样任何人更新了 API 结构图只要同步改一下文本文件提交后自动生成最新的矢量图和位图文档站点直接引用这两个文件即可。文本文件本身就是代码的一部分走 Code Review 流程改了什么一目了然。这个思路把“画图”彻底变成了“改文本”对团队协作来说非常友好。6. 常见问题与排查技巧6.1 转换后图形错位或框线断裂表现生成的 SVG 里矩形边缘该接上的地方没接上或者线条歪斜。原因几乎都是源文本没有对齐。看下面这两个例子对不齐的----- | | ----对齐的------ | | ------a2s 的图形识别依赖框线在坐标上的连续性只要有一行少了几个空格矩形就会少一条边或多一个偏移。排查方法先用支持等宽字体的编辑器VS Code、Sublime 都行打开源文件肉眼检查每一行右侧是否对齐。也可以用脚本检查每行长度with open(input.txt, r, encodingutf-8) as f: lines f.readlines() lengths {len(line.rstrip()) for line in lines} print(lengths)如果集合里元素个数大于 1说明各行长度不一致先手工对齐再说。6.2 中文字符导致的宽度问题表现框内中文内容显示正常但框线或相邻结构错位。原因中文全角字符宽度大约是英文的两倍。如果char_w参数按英文字符宽度设置遇到中文就会把坐标计算偏。解决办法我的经验是给char_w设置成英文的两倍比如英文字符网格是 8那中文场景就设 12 或 16具体要看字体。更稳的办法是源文本里不让中文参与框线的坐标计算——中文字符只在矩形内部作为文本内容出现框线完全用、-、|这些 ASCII 字符绘制。6.3 SVG 字体依赖导致跨平台显示不一致表现同一个 SVG在自己机器上浏览器里显示正常发给同事后文字字体变了排版乱了。原因SVG 本身不内嵌字体它依赖系统字体。a2s 生成的 SVG 里文字通常使用默认字体族比如sans-serif在不同操作系统上渲染结果不同。解决办法如果你对字体有强要求生成 SVG 后直接用文本编辑器打开它在text元素上把font-family改成指定字体比如text font-familyCourier New, monospaceProducer/text或者直接在生成后写一个小脚本用字符串替换统一加字体with open(output.svg, r, encodingutf-8) as f: content f.read() content content.replace( text, text font-familyArial, sans-serif ) with open(output.svg, w, encodingutf-8) as f: f.write(content)6.4 转换后 SVG 整体太小或太大表现SVG 在浏览器里打开图形小得像邮票或者大得溢出屏幕。原因默认画布尺寸是按字符网格和文本行数推算出来的有时候源文本行数很多但每行宽度很窄导致画布比例失衡。解决办法设置画布尺寸。from a2s import tune tune.set_params(doc_w1024, doc_h768)需要注意这改变的是整体画布不是缩放倍率。如果你想要的只是等比缩放更推荐生成后用 Pillow 或浏览器再处理因为改画布会影响图形元素坐标计算可能导致间距变化。7. 我的实操心得与建议最后分享几个我自己在实践中总结出来的经验不一定写进官方文档但很管用。第一源文本的“干净度”决定了a2s的上限。你花十分钟手工整理一个对齐的 ASCII art比花一小时调参更有效。我的习惯是任何交给 a2s 的文本先放在等宽字体下检查一遍特别留意框线转角处有没有多余空格短线有没有漏接。第二别让 a2s 承担太多“审美工作”。a2s 擅长的是把文本结构精确地转成矢量图形但配色、字体、边框粗细这些审美层面的东西生成之后再处理反而更顺手。SVG 本身就是文本格式你可以用脚本批量改颜色也可以拖进绘图工具二次加工。拿到的是一份干净的几何图形后面想怎么打扮都随你。第三把文本图当作源码来管理。一旦你习惯了“文本 - SVG”的自动化流程你会自然地想给所有架构图维护一份文本源文件。文本文件不但在 Git 里可 diff还能被代码评审。以后图变了评审的人看一眼文本 diff马上知道动了什么。这是传统绘图工具完全做不到的协作优势。第四a2s 不是万能的。过于复杂的图形比如有曲线箭头、多层嵌套圆角框、颜色渐变的架构图用 a2s 硬生成会非常痛苦效果也不好看。我的建议是简单规整的框图、网络拓扑、模块关系图用 a2s 自动化复杂的设计稿老老实实用专门工具画。工具没有高低之分关键是选对场景。如果你手头正好有一堆文本框图不妨试着跑一遍 a2s。它可能不会帮你画出一张惊艳的海报但一定能帮你把“能看”变成“好用”把藏在代码里的技术图转化成真正可复用的项目资产。