树莓派Python二维码生成实战:从qrcode库到Flask API部署
发布时间:2026/8/19 9:00:10 作者:尧图编辑部 阅读量:1,286

1. 项目概述为什么要在树莓派上用Python生成二维码如果你手头有一台树莓派并且想让它从单纯的“小电脑”变成一个能与人、与物交互的智能终端那么生成二维码绝对是一个既实用又有趣的切入点。这个项目听起来简单但背后串联了Python编程、图像处理、硬件交互和实际应用场景是检验你软硬件结合能力的绝佳试金石。我最初接触这个需求是因为一个智能储物柜项目。每个柜门需要一个唯一的二维码作为“数字钥匙”用户扫码即可开锁。用树莓派来动态生成并显示这些二维码成本低廉且部署灵活。从那时起我就在各种项目中反复使用这套技术栈从会议签到系统到物联网设备配网它都扮演了关键角色。简单来说这个项目就是教会你的树莓派使用Python语言“画”出二维码图片并可以进一步控制这块二维码的用途——是显示在屏幕上还是打印出来或是通过网络发送出去。它非常适合物联网开发者、创客、教育工作者以及任何想给树莓派项目增加一个便捷交互入口的朋友。无论你是Python新手还是有一定经验的开发者都能从中获得清晰的实现路径和可复用的代码。2. 核心思路与方案选型在树莓派上用Python生成二维码核心流程可以拆解为三个步骤生成二维码图像、处理图像、输出图像。每一步都有多种工具和方法可选我们的选型需要综合考虑树莓派的硬件特性如ARM架构、有限的性能、Python生态的成熟度以及最终的使用场景。2.1 二维码生成库的选择Python生成二维码的库不少主流的有qrcode、pyqrcode、segno等。经过多次项目实践我几乎无一例外地选择qrcode库原因如下简单易用API友好qrcode的接口设计非常直观几行代码就能生成一个标准的二维码图片对新手极其友好。功能全面它不仅支持生成基本的QR Code还能方便地设置纠错等级、版本大小、边框等参数并且内置了Pillow库支持能直接生成PIL图像对象便于后续处理。生态成熟文档丰富作为最流行的二维码生成库之一其社区活跃遇到问题容易找到解决方案。它也是许多大型项目的依赖稳定性经过考验。性能适中在树莓派3B/4B这样的硬件上生成一个普通复杂度的二维码速度很快完全能满足实时或准实时的需求。pyqrcode也是一个选择它更轻量但功能相对基础且默认输出SVG矢量图或PNG需要依赖pypng库在图像处理的便捷性上稍逊一筹。segno库较新功能强大支持更多二维码变种如艺术二维码但学习曲线稍陡。对于绝大多数应用场景qrcodePillow的组合是“甜点区”。2.2 图像处理与输出的考量生成二维码图像对象后我们需要决定如何“交付”它。这里有几个常见方向保存为图片文件最简单直接的方式。将二维码保存为PNG或JPEG格式到树莓派的SD卡上之后可以通过邮件、网页或U盘传递。在屏幕上显示如果你为树莓派连接了显示器或触摸屏可以直接将二维码图像显示出来。这需要用到图形界面库如TkinterPython自带轻量或PyGame适合动态内容。通过网络接口提供构建一个简单的Web服务器例如使用Flask当用户访问特定网址时动态生成并返回二维码图片。这在需要远程获取二维码的场景下非常有用。与硬件结合例如将二维码发送到热敏小票打印机打印出来或者结合摄像头实现“生成-扫描”的闭环测试。考虑到树莓派常作为无头服务器无显示器运行以及物联网项目对远程访问的需求“生成并保存为文件”和“提供Web API”是两种最实用、最高频的方案。本篇文章将重点深入这两种并简要介绍屏幕显示的方法。2.3 树莓派环境准备要点树莓派官方系统Raspbian/Raspberry Pi OS已经预装了Python3这是我们工作的基础。你需要通过SSH或直接连接终端进行操作。首要任务是安装必要的Python库。这里有一个关键细节务必使用pip3而不是pip。因为系统默认的pip可能指向Python2而Python2已不再被维护。我们的所有操作都基于Python3。安装命令如下sudo apt update sudo apt upgrade -y pip3 install qrcode[pil]qrcode[pil]这种写法会同时安装qrcode库和其所需的PillowPIL的分支图像处理库一步到位。注意在树莓派上使用pip安装时如果遇到速度慢或超时可以考虑使用国内镜像源例如pip3 install qrcode[pil] -i https://pypi.tuna.tsinghua.edu.cn/simple3. 核心代码解析与基础生成实战让我们从最核心的代码开始一行行拆解理解每个参数的意义和调整方法。3.1 安装验证与最小示例安装完成后创建一个Python文件比如generate_qr_simple.py。import qrcode # 1. 创建QRCode对象这是核心控制器 qr qrcode.QRCode( version1, error_correctionqrcode.constants.ERROR_CORRECT_L, box_size10, border4, ) # 2. 向二维码中添加数据 data https://www.raspberrypi.org qr.add_data(data) # 3. 生成二维码矩阵内部计算 qr.make(fitTrue) # 4. 创建图像并保存 img qr.make_image(fill_colorblack, back_colorwhite) img.save(simple_qr.png) print(基础二维码已生成并保存为 simple_qr.png)运行这个脚本 (python3 generate_qr_simple.py)你会在当前目录下得到一个名为simple_qr.png的二维码图片用手机扫码就会跳转到树莓派官网。3.2 关键参数深度解读上面代码中的QRCode初始化参数是控制二维码外观和容错能力的核心值得深入理解version 范围1到40。它决定了二维码的大小数据容量。Version 1是21x21的矩阵每增加一个版本每边增加4个模块。如果设置为None或配合fitTrue库会自动选择能容纳数据的最小版本。实操建议除非你明确知道所需容量否则通常设置versionNone并让库自动决定或者先使用fitTrue自动适配。error_correction 纠错等级决定了二维码在部分污损或遮挡后仍能被识别的能力。它有四个常量ERROR_CORRECT_L(L级): 约可恢复7%的数据错误。ERROR_CORRECT_M(M级): 约可恢复15%的数据错误。这是默认值也是最常用的平衡选择。ERROR_CORRECT_Q(Q级): 约可恢复25%的数据错误。ERROR_CORRECT_H(H级): 约可恢复30%的数据错误。 等级越高容错能力越强但二维码本身会变得更复杂数据点更密。经验之谈对于打印出来可能被折叠、污损的二维码或者显示在屏幕上可能因反光、像素问题导致识别困难的场景建议使用ERROR_CORRECT_H。对于纯数字环境传输的清晰图片ERROR_CORRECT_M足够。box_size 每个“小方块”二维码中的一个数据模块在最终图像里占据的像素大小。它直接控制生成图片的物理尺寸。box_size10意味着每个点用10x10的像素块表示。调整技巧如果你生成的二维码在手机上难以扫描可以尝试增大box_size如20或30来提高对比度和清晰度。反之如果需要生成尺寸很小的图片可以减小它但不要低于2否则可能无法识别。border 二维码图像四周的空白边距单位是“模块数”注意不是像素。border4是标准规定的最小值。增大边框可以使扫描器更容易定位二维码尤其是在复杂背景上。常见误区有人为了节省空间设为0这会导致许多扫码软件无法识别。强烈建议保持至少为4。3.3 高级定制颜色、样式与嵌入Logo基础的二维码是黑白的但我们可以让它更美观或更具品牌感。修改前景色和背景色在make_image()方法中设置fill_color和back_color。颜色可以用颜色名称字符串如blue也可以是十六进制字符串如#FF5733或RGB元组(255, 87, 51)。img qr.make_image(fill_color#E74C3C, back_color#2C3E50) # 深蓝背景亮红色前景为二维码添加中心Logo这是一个很常见的需求比如公司二维码中间放logo。思路是先生成标准二维码然后用Pillow打开Logo图片将其缩放至合适大小最后粘贴到二维码中央。import qrcode from PIL import Image def generate_qr_with_logo(data, logo_path, output_path): # 生成基础二维码 qr qrcode.QRCode(error_correctionqrcode.constants.ERROR_CORRECT_H) # 高容错为logo遮挡预留空间 qr.add_data(data) qr.make(fitTrue) qr_img qr.make_image(fill_colorblack, back_colorwhite).convert(RGB) # 打开并处理Logo logo Image.open(logo_path) # 计算logo的合适大小例如二维码大小的1/4 qr_width, qr_height qr_img.size logo_max_size qr_width // 4 # 等比例缩放logo logo.thumbnail((logo_max_size, logo_max_size), Image.Resampling.LANCZOS) # 计算粘贴位置居中 logo_pos ((qr_width - logo.size[0]) // 2, (qr_height - logo.size[1]) // 2) # 粘贴Logo qr_img.paste(logo, logo_pos) # 保存 qr_img.save(output_path) print(f带Logo的二维码已保存至 {output_path}) # 使用示例 generate_qr_with_logo(https://your-company.com, logo.png, qr_with_logo.png)重要提示添加Logo会覆盖部分二维码数据因此必须将纠错等级设置为ERROR_CORRECT_H(H级)利用其最高的纠错能力来补偿被遮挡的数据区域确保二维码依然可被扫描。4. 实战场景一生成并保存为文件自动化脚本在树莓派上我们经常需要自动化地批量生成二维码。例如为物联网设备生成唯一的配置二维码或者为一系列产品生成序列号二维码。4.1 批量生成与动态命名假设我们有一个设备列表需要为每个设备生成一个包含其ID和配置信息的二维码。import qrcode import json import os def generate_device_qr(device_id, ip_address, output_dirqr_codes): 为单个设备生成二维码 # 构建二维码内容可以是JSON字符串方便解析 device_info { device_id: device_id, ip: ip_address, type: sensor_node_v2 } qr_data json.dumps(device_info) # 将字典转为JSON字符串 # 创建输出目录如果不存在 os.makedirs(output_dir, exist_okTrue) # 配置并生成二维码 qr qrcode.QRCode( versionNone, # 自动选择版本 error_correctionqrcode.constants.ERROR_CORRECT_M, box_size12, border4, ) qr.add_data(qr_data) qr.make(fitTrue) img qr.make_image(fill_colorblack, back_colorwhite) # 动态命名文件 filename os.path.join(output_dir, fdevice_{device_id}.png) img.save(filename) print(f已生成: {filename}) return filename # 模拟设备列表 devices [ {id: SN001, ip: 192.168.1.101}, {id: SN002, ip: 192.168.1.102}, {id: SN003, ip: 192.168.1.103}, ] # 批量生成 for device in devices: generate_device_qr(device[id], device[ip]) print(批量生成完成)这个脚本会创建一个qr_codes文件夹并在其中生成device_SN001.png、device_SN002.png等文件。二维码内容是可解析的JSON手机扫码后可以使用相应的App来解析并获取设备信息。4.2 集成到系统工作流结合cron定时任务树莓派的一个强大之处是可以作为小型服务器7x24小时运行。我们可以结合Linux的cron定时任务让二维码生成脚本定期自动执行。例如每天凌晨2点从一个外部API获取新的设备列表并生成二维码首先将上面的批量生成逻辑写成一个完整的脚本比如/home/pi/scripts/generate_daily_qr.py。编辑cron任务表crontab -e在文件末尾添加一行0 2 * * * /usr/bin/python3 /home/pi/scripts/generate_daily_qr.py /home/pi/logs/qr_generator.log 210 2 * * *表示每天2:00 AM执行。/usr/bin/python3是Python3解释器的绝对路径使用which python3命令查看你的路径。 ...log 21将脚本的标准输出和错误输出都重定向到一个日志文件方便后续排查问题。这样你就建立了一个全自动的二维码生成流水线无需人工干预。5. 实战场景二构建Web API动态生成二维码对于需要即时生成、动态内容或远程访问的场景将树莓派变成一个二维码生成服务器是最优雅的方案。我们使用轻量级的Flask框架来实现。5.1 搭建基础的Flask应用首先安装Flaskpip3 install flask然后创建qr_server.pyfrom flask import Flask, send_file, request, make_response import qrcode import io import time app Flask(__name__) app.route(/qr) def generate_qr_api(): 基础二维码生成API 请求参数text (二维码内容) 返回PNG图片流 # 从URL参数中获取要编码的文本 qr_text request.args.get(text, ) if not qr_text: return 错误请提供 text 参数例如/qr?textHelloPi, 400 # 生成二维码 qr qrcode.QRCode( versionNone, error_correctionqrcode.constants.ERROR_CORRECT_M, box_size10, border4, ) qr.add_data(qr_text) qr.make(fitTrue) img qr.make_image(fill_colorblack, back_colorwhite) # 将图像保存到内存中的字节流而不是文件 img_byte_arr io.BytesIO() img.save(img_byte_arr, formatPNG) img_byte_arr.seek(0) # 将指针移回流的开头 # 创建响应直接返回图片流 response make_response(send_file(img_byte_arr, mimetypeimage/png)) # 添加缓存控制头避免浏览器缓存旧的二维码对于动态内容很重要 response.headers[Cache-Control] no-store, no-cache, must-revalidate, max-age0 return response if __name__ __main__: # 运行Flask应用监听所有IP0.0.0.0端口5000 # debugTrue 仅用于开发生产环境应设为False app.run(host0.0.0.0, port5000, debugFalse)5.2 运行与访问在树莓派终端运行python3 qr_server.py你会看到输出提示服务运行在http://0.0.0.0:5000。现在在同一局域网内的任何设备手机、电脑上打开浏览器访问http://[你的树莓派IP地址]:5000/qr?textHello from Raspberry Pi!例如http://192.168.1.100:5000/qr?textHello from Raspberry Pi!浏览器就会显示一个包含“Hello from Raspberry Pi!”文本的二维码图片。你可以右键保存这张图片。5.3 高级API功能扩展一个生产可用的API需要考虑更多细节1. 支持POST请求和JSON数据有时需要传递更复杂或更长的数据如JSON配置。app.route(/qr/json, methods[POST]) def generate_qr_from_json(): data request.get_json() if not data or content not in data: return jsonify({error: Invalid JSON or missing content field}), 400 qr_text data[content] # ... 生成二维码的代码同上 ... # 返回JSON响应包含成功信息和图片的Base64编码另一种方式 import base64 buffered io.BytesIO() img.save(buffered, formatPNG) img_str base64.b64encode(buffered.getvalue()).decode() return jsonify({status: success, image_base64: img_str})2. 增加请求参数定制样式让API更灵活允许调用者指定颜色、大小等。app.route(/qr/advanced) def generate_qr_advanced(): qr_text request.args.get(text, ) box_size int(request.args.get(box_size, 10)) fill_color request.args.get(fill_color, black) back_color request.args.get(back_color, white) # ... 使用这些参数生成二维码 ... qr qrcode.QRCode(box_sizebox_size, ...) img qr.make_image(fill_colorfill_color, back_colorback_color) # ... 返回图片 ...访问示例http://192.168.1.100:5000/qr/advanced?textTestbox_size15fill_colorblue3. 添加简单的认证API Key防止你的二维码生成服务被滥用。API_KEYS {my_secret_key_123: True} app.before_request def check_api_key(): if request.endpoint in [generate_qr_api, generate_qr_advanced]: # 保护特定路由 provided_key request.args.get(api_key) if not provided_key or provided_key not in API_KEYS: return 未授权访问, 401访问时需带上参数?text...api_keymy_secret_key_1235.4 使用生产级服务器部署Flask自带的开发服务器不适合生产环境。我们可以使用Gunicorn这类WSGI服务器来提升性能和稳定性。安装Gunicornpip3 install gunicorn使用Gunicorn启动应用cd /path/to/your/code gunicorn -w 2 -b 0.0.0.0:5000 qr_server:app-w 2: 使用2个工作进程。-b 0.0.0.0:5000: 绑定地址和端口。qr_server:app: 模块名和Flask应用实例名。为了让它开机自启和后台运行可以创建一个systemd服务文件 (/etc/systemd/system/qr-generator.service)[Unit] DescriptionQR Code Generator Service Afternetwork.target [Service] Userpi WorkingDirectory/home/pi/qr_code_project ExecStart/usr/local/bin/gunicorn -w 2 -b 0.0.0.0:5000 qr_server:app Restartalways [Install] WantedBymulti-user.target然后运行sudo systemctl daemon-reload sudo systemctl enable qr-generator.service sudo systemctl start qr-generator.service这样你的二维码生成API服务就会在树莓派启动时自动运行并且崩溃后会自动重启。6. 实战场景三在树莓派屏幕上显示二维码如果你为树莓派连接了显示器如官方触摸屏或HDMI显示器可以直接将生成的二维码显示出来用于信息展示、临时Wi-Fi密码分享等场景。6.1 使用Tkinter创建图形界面显示Tkinter是Python自带的GUI库无需额外安装非常适合这种简单的图像显示任务。import qrcode from PIL import Image, ImageTk import tkinter as tk from tkinter import ttk def show_qr_on_screen(dataHello Raspberry Pi Display): # 生成二维码图像 qr qrcode.QRCode(box_size10, border4) qr.add_data(data) qr.make(fitTrue) pil_img qr.make_image(fill_colorblack, back_colorwhite) # 创建Tkinter窗口 root tk.Tk() root.title(树莓派二维码显示器) # 将PIL图像转换为Tkinter可用的PhotoImage tk_img ImageTk.PhotoImage(pil_img) # 创建标签组件并显示图片 label ttk.Label(root, imagetk_img) label.pack(padx20, pady20) # 可选添加一个文本框显示二维码内容 content_label ttk.Label(root, textf内容: {data}, font(Arial, 12)) content_label.pack(pady(0, 20)) # 运行主循环 root.mainloop() if __name__ __main__: # 可以在这里修改要显示的内容 show_qr_on_screen(https://www.raspberrypi.com/products/raspberry-pi-5/)运行这个脚本一个包含二维码的窗口就会弹出。这种方法简单快捷但功能相对基础。6.2 创建交互式二维码显示器我们可以做一个更实用的小工具一个输入框输入文本后点击按钮实时更新显示的二维码。import qrcode from PIL import Image, ImageTk import tkinter as tk from tkinter import ttk, messagebox class QRDisplayApp: def __init__(self, root): self.root root self.root.title(交互式二维码生成器) self.root.geometry(500x600) # 输入区域 input_frame ttk.Frame(root) input_frame.pack(pady10, fillx, padx20) ttk.Label(input_frame, text输入二维码内容:).pack(anchorw) self.text_var tk.StringVar(value初始内容) self.entry ttk.Entry(input_frame, textvariableself.text_var, width50) self.entry.pack(sideleft, fillx, expandTrue, padx(0, 10)) self.entry.bind(Return, self.update_qr) # 按回车键也更新 ttk.Button(input_frame, text生成二维码, commandself.update_qr).pack(sideleft) # 显示区域 self.display_frame ttk.LabelFrame(root, text二维码预览) self.display_frame.pack(pady20, padx20, fillboth, expandTrue) # 初始一个空图像标签 self.qr_label ttk.Label(self.display_frame) self.qr_label.pack(expandTrue) # 底部信息 info_label ttk.Label(root, text修改上方文本并点击按钮或按回车键以更新二维码, font(Arial, 9)) info_label.pack(pady(0, 10)) # 初始化显示 self.update_qr() def update_qr(self, eventNone): data self.text_var.get().strip() if not data: messagebox.showwarning(输入为空, 请输入一些内容来生成二维码。) return try: qr qrcode.QRCode(box_size8, border4) qr.add_data(data) qr.make(fitTrue) pil_img qr.make_image(fill_color#2C3E50, back_color#ECF0F1) # 使用更柔和的颜色 # 调整图像大小以适应窗口可选 # pil_img pil_img.resize((300, 300), Image.Resampling.LANCZOS) tk_img ImageTk.PhotoImage(pil_img) self.qr_label.configure(imagetk_img) self.qr_label.image tk_img # 保持引用防止被垃圾回收 self.display_frame.configure(textf二维码预览 - 内容长度: {len(data)} 字符) except Exception as e: messagebox.showerror(生成错误, f生成二维码时出错:\n{e}) if __name__ __main__: root tk.Tk() app QRDisplayApp(root) root.mainloop()这个程序创建了一个带输入框和按钮的界面实现了二维码的实时生成和显示非常适合需要动态展示信息的场景比如在会议中展示一个随时变化的投票链接。7. 常见问题、性能优化与排查技巧在实际部署和运行过程中你可能会遇到一些问题。以下是我在多个项目中总结的经验和解决方案。7.1 二维码扫描失败问题排查这是最常见的问题。如果生成的二维码手机扫不出来请按以下步骤排查检查内容是否过长或过于复杂二维码的数据容量有限。纯文本的话Version 40的L级纠错也只能容纳约4000个字符。如果内容是一个很长的URL或JSON尝试缩短它比如使用URL短链接服务或者检查是否因内容太长导致自动选择的版本过高使得模块过密难以识别。可以尝试固定一个较低的version如5或10并增大box_size。检查纠错等级和Logo遮挡如果你在二维码中央添加了Logo必须使用ERROR_CORRECT_H。使用其他低级纠错Logo遮挡部分数据后很可能导致无法解码。检查颜色对比度确保前景色和背景色有足够对比度。避免使用浅色前景配浅色背景如黄色前景配白色背景。经典的黑白搭配是最可靠的。如果必须使用彩色确保亮度差足够大。检查边框border边框绝对不能小于4。有些扫码软件需要这个空白区域来定位二维码。可以尝试将border增加到6或8。检查物理显示/打印质量屏幕显示确保屏幕干净无反光。如果二维码显示在网页或应用中检查图片是否被CSS压缩导致模糊。尝试增大box_size参数。打印输出打印机分辨率可能不足。确保打印清晰无墨渍晕染。打印后可以用手机先扫一下测试。使用专业的扫码工具测试不要只依赖微信扫一扫。可以尝试使用“QR Code Reader”、“Barcode Scanner”等更专业的App它们通常会提供更详细的解码信息和错误提示。在线验证工具将生成的二维码图片上传到在线二维码解码网站如 https://zxing.org/w/decode.jspx看能否成功解析。这能帮你判断是生成问题还是扫描环境问题。7.2 树莓派性能与内存优化当需要高频、大批量生成二维码时比如一次生成上千个需要注意资源消耗。单次生成优化qrcode库本身效率很高。主要瓶颈在图像保存I/O操作。如果批量生成避免在循环中频繁打开关闭文件可以考虑使用BytesIO内存流先处理最后再统一写入或者使用多线程/异步IO来并行处理I/O。内存管理PIL图像对象会占用内存。在批量处理的脚本中生成并保存完一个二维码后及时将图像对象变量指向None或使用del语句并手动调用垃圾回收 (import gc; gc.collect())有助于在长时间运行的脚本中防止内存缓慢增长。Web服务优化对于Flask API如果并发请求量很大使用Gunicorn等WSGI服务器并配置合适的工作进程数-w是关键。对于树莓派4B2-4个worker进程通常是安全的。此外可以考虑对相同的请求内容进行缓存避免重复生成。可以使用functools.lru_cache装饰器缓存make_image的结果注意仅适用于参数完全相同的请求。7.3 高级技巧生成微型二维码微型QR标准QR Code有最小尺寸限制。如果你需要极小的二维码例如印在非常小的标签上可以研究微型二维码Micro QR。segno库原生支持生成Micro QR。虽然应用场景相对小众但在对尺寸有极端要求的嵌入式设备或微型印刷品上这是一个可行的解决方案。使用方法与qrcode类似但需要额外注意其更严格的数据容量和版本限制。7.4 安全性考量二维码内容安全二维码可以编码任何文本包括恶意URL或脚本。如果你构建的Web API允许用户输入任意内容生成二维码务必注意防范跨站脚本XSS等攻击。虽然二维码本身是图片但生成它的参数可能被注入。对输入进行适当的过滤和长度限制是良好的实践。API访问控制如前面所述公开的生成API可能被滥用消耗树莓派资源。通过API Key、请求频率限制如使用Flask-Limiter库或IP白名单来控制访问。敏感信息避免将密码、密钥等敏感信息直接以明文形式编码进二维码。如果必须考虑使用加密后再编码或者二维码仅包含一个临时令牌通过安全的后端接口换取真实信息。通过以上从原理到实践从基础到进阶的详细拆解你应该已经掌握了在树莓派上使用Python生成二维码的完整技能链。这套方案稳定、灵活且易于扩展足以支撑起从个人实验到小型生产环境的各类需求。最重要的是动手去实现它并根据你的具体项目需求进行调整和优化这才是掌握技术的唯一途径。