1. 为什么树莓派开发需要虚拟环境?

如果你刚拿到一块树莓派,兴冲冲地准备用它来做个带图形界面的小项目,比如一个智能家居控制面板或者一个数据监控仪表盘,你可能会直接上手 pip install PySide2。别急,我当年也是这么干的,结果就是系统里的 Python 被搞得一团糟,装了这个包,那个项目就报错,最后不得不重刷系统。在树莓派这种资源有限、系统相对“娇贵”的设备上,直接往系统 Python 里塞各种开发包,绝对是“自杀式”操作。

为什么这么说呢?树莓派默认的 Raspberry Pi OS(以前叫 Raspbian)buster 版本,自带的是 Python 3.7。系统本身很多功能都依赖这个 Python 环境。如果你用 sudo pip install 强行安装或升级某个包,很可能会破坏系统组件的依赖关系,导致一些系统工具甚至桌面环境出问题。更麻烦的是,不同的项目可能需要不同版本的库,比如项目A需要 PySide2 5.15.2,项目B需要 5.12.3,在同一个 Python 环境里根本无法共存。

这时候,Python 虚拟环境就是你的救命稻草。它相当于给你的每个项目单独开辟一个干净的“小房间”,在这个房间里,你可以随意安装、升级、降级任何 Python 包,而不会影响到系统环境和其他项目。这对于树莓派这种“一机多用”(可能同时跑着家庭服务器、下载机、开发机)的场景来说,简直是刚需。

但是,树莓派(尤其是 armv7l/arm32 架构)上搭建虚拟环境,和你在 Windows 或 x86 的 Linux 电脑上有点不一样。网上很多教程让你用 venv 或者 virtualenv,在树莓派上不是不行,但会遇到一些依赖库编译的问题,尤其是涉及到 Qt(PyQt5/PySide2 的底层)这种大型 GUI 框架时,很容易踩坑。经过我多年的折腾,我发现 pipenv 是更适合树莓派 arm 平台的选择,特别是它有一个 --site-packages 的选项,能巧妙地解决我们后面要遇到的大麻烦。

2. 系统准备与基础依赖安装

在开始配置虚拟环境和安装 PySide2 之前,我们需要先把树莓派的基础开发环境搭建好。这个过程就像盖房子前先打好地基、接通水电一样,必不可少。

首先,确保你的树莓派已经连接网络,并且最好已经完成了系统换源和 pip 换源。这一步能极大提升后续安装软件包的速度。如果你还没做,可以简单执行 sudo raspi-config,选择本地化选项,更换软件源为国内的镜像(如清华、中科大源)。pip 源可以在用户目录下创建或修改 ~/.pip/pip.conf 文件来配置。

接下来,我们需要安装一系列编译和开发工具。因为无论是系统包还是后续可能从源码编译的 Python 包,都需要这些工具。打开终端,依次执行以下命令:

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install build-essential -y
sudo apt-get install clang clang-format -y

build-essential 包含了 gcc、g++、make 等核心编译工具链。clang 是另一个编译器,有时在 arm 平台上编译某些库比 gcc 更顺利。执行完这些,你的树莓派就具备了编译代码的基本能力。

然后,是安装 Qt 开发环境。即使我们主要用 Python 的 PySide2 来写界面,但安装完整的 Qt 开发套件有两个巨大好处:第一,你能得到 Qt Designer 这个强大的可视化界面设计工具,虽然我们最终在树莓派上可能用不到它的设计功能,但安装它时会同时安装许多关键的 Qt 库文件,这些是 PySide2 运行时所依赖的;第二,保留了未来用 C++ 写 Qt 程序的可能性。命令如下:

sudo apt-get install qt5-default -y
sudo apt-get install qtcreator -y
sudo apt-get install qtdeclarative5-dev -y

安装过程可能会比较长,因为 Qt 是一个庞大的框架。安装完成后,你可以在应用菜单里找到 Qt Creator。不过先别急着打开,我们还有一个关键配置。由于树莓派桌面环境的一些兼容性问题,需要将 Qt 的界面主题引擎从 gtk3 切换回更稳定的 gtk2。编辑配置文件:

sudo nano /etc/xdg/qt5ct/qt5ct.conf

找到文件中类似 style=gtk3 的行(如果文件是空的或没有这一行,可以手动添加),将其修改为 style=gtk2。然后按 Ctrl+X,再按 Y 和回车保存退出。这个改动能避免后续运行 PySide2 程序时可能出现的界面样式错乱或崩溃问题。

3. 使用 pipenv 创建“特殊”的虚拟环境

地基打好了,现在开始搭建我们的“项目专属房间”。前面提到,在树莓派上我推荐使用 pipenv,而不是传统的 venvpipenv 不仅管理虚拟环境,还整合了依赖管理(类似 requirements.txt 但更强大),用起来更省心。

首先,安装 pipenv切记,一定要用 pip3 install --user pipenv 安装到用户目录,不要用 sudo

pip3 install --user pipenv

安装完成后,把用户本地 bin 目录添加到 PATH 环境变量,这样可以直接在终端里运行 pipenv 命令。可以将下面这行添加到 ~/.bashrc 文件的末尾:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

现在,进入你的项目目录,比如 ~/my_pyside2_project,然后执行创建虚拟环境的魔法命令:

cd ~/my_pyside2_project
pipenv --python 3 --site-packages

看到那个 --site-packages 了吗?这就是针对树莓派 PySide2 开发的关键所在。这个参数允许你创建的虚拟环境访问并重用系统 Python 环境中已经安装的包

为什么要这么做?因为 PySide2(以及 PyQt5)在 arm 平台上的安装非常特殊。它们依赖大量底层的 Qt 库(C++写的),通过 pip install 安装极其困难,几乎都会在编译阶段卡住。而通过系统包管理器 apt 安装的 PySide2,是已经为树莓派 armv7l 架构预编译好的,开箱即用。但 apt 安装的包是装在系统 Python 目录下的。--site-packages 这个选项,就在你的虚拟环境和系统包目录之间架起了一座桥,让你既享受虚拟环境的隔离性,又能直接调用系统里那个现成的、稳定的 PySide2。

执行命令后,pipenv 会创建一个基于 Python 3 的虚拟环境,并生成 Pipfile 文件。你可以通过 pipenv shell 激活这个环境。激活后,命令行提示符前面会有环境名,表示你已经进入了这个“小房间”。

4. 在树莓派上正确安装 PySide2

好了,虚拟环境准备好了,现在该安装主角 PySide2 了。如果你在激活的 pipenv 环境里直接运行 pip install PySide2,你会经历一个漫长的等待,然后大概率会看到编译错误而失败。这是因为 PySide2 的官方 PyPI 上没有提供 arm32 架构的预编译轮子(wheel),需要从源码编译,而这个过程在树莓派 4B 上可能要几个小时,并且对内存和交换空间要求很高,极易失败。

正确的方法,是利用我们之前搭建的“桥梁”。由于我们创建环境时使用了 --site-packages,系统里通过 apt 安装的包已经对虚拟环境可见了。所以,我们根本不需要在虚拟环境里“安装” PySide2,只需要确保系统里已经装好了就行。

在终端中(先退出虚拟环境,或者新开一个终端),执行以下命令来安装系统级的 PySide2:

sudo apt update
sudo apt install pyside2* python3-pyside2* -y

这个命令会安装所有以 pyside2python3-pyside2 开头的包,确保组件完整。安装完成后,你可以回到项目目录,激活 pipenv 环境,然后启动 Python 解释器验证一下:

cd ~/my_pyside2_project
pipenv shell
python3

在 Python 交互界面中输入:

import PySide2.QtCore
print(PySide2.__version__)

如果能够成功打印出版本号(比如 5.14.1),恭喜你,PySide2 已经在你的虚拟环境中可用了!这背后的原理是,当 Python 在虚拟环境中导入一个模块时,它会先在虚拟环境的 site-packages 里找,如果找不到,就会去 --site-packages 允许访问的系统 site-packages 里找。于是,我们巧妙地“借用”了系统的安装成果。

这里再提一下 PyQt5。安装方式类似:sudo apt install pyqt5* python3-pyqt5。但正如原始文章提到的,从协议角度,PySide2(基于 LGPL)比 PyQt5(基于 GPL)对商业闭源应用更友好。除非有历史包袱,否则新项目建议直接用 PySide2。

5. 处理 UI 和资源文件:跨平台的坑与解决方案

用 PySide2 开发图形界面,通常我们会用 Qt Designer(一个可视化拖拽工具)来设计界面,保存为 .ui 文件。同时,如果界面用了图标、图片等资源,我们会将它们打包进一个 .qrc 资源文件。这两个文件都需要转换成 Python 代码才能被程序使用。这里就有一个树莓派 arm 平台特有的大坑。

你会发现,通过 apt 安装的 pyside2 包,并没有包含 pyside2-uicpyside2-designer 这两个命令行工具。也就是说,你无法直接在树莓派上把 .ui 文件转换成 .py 文件。尝试安装 pyside2-tools 包也往往找不到。

那怎么办呢?我的实战经验是:在 Windows 或 macOS 开发机上完成转换工作。这是一种跨平台开发的工作流。

  1. 在开发机(如Windows)上,用 pip 安装 PySide2:pip install PySide2。这会同时安装 pyside2-uicpyside2-rcc 工具。
  2. 在开发机上,使用 Qt Designer(可以从 PySide2 安装目录找到,或单独安装)设计界面,保存为 mainwindow.ui
  3. 在开发机的命令行中,使用 pyside2-uic 转换 UI 文件:
    pyside2-uic mainwindow.ui -o ui_mainwindow.py
    
    这样会生成一个 ui_mainwindow.py 文件,里面定义了界面的 Python 类。
  4. 对于资源文件(如图标),在开发机上创建一个 resources.qrc 的 XML 文件,描述资源路径,然后用 pyside2-rcc 转换:
    pyside2-rcc resources.qrc -o resources_rc.py
    

重点来了:这两个生成的 .py 文件,可以直接复制到树莓派上使用吗?

对于 ui_mainwindow.py答案是肯定的。只要两边用的都是 PySide2(且版本不要差太多),这个由 pyside2-uic 生成的界面代码是跨平台兼容的,可以直接复制到树莓派项目里。

但是,对于 resources_rc.py答案是否定的!这是我踩过的一个大坑。在 Windows 上用 pyside2-rcc 生成的资源文件,在 Linux(树莓派)的 PySide2 环境下导入时会报错,原因是编码和内部结构有细微的跨平台差异。

解决方案是:在树莓派上重新编译一次资源文件。 你需要把原始的 .qrc 文件和图片资源一起复制到树莓派上。然后在树莓派上,虽然我们没有 pyside2-uic,但幸运的是,通过 apt 安装的 PySide2 包提供了 pyside2-rcc 命令!在树莓派终端里(可以在虚拟环境内,也可以在系统环境,只要 PySide2 模块能导入),执行:

pyside2-rcc resources.qrc -o resources_rc.py

这样生成的 resources_rc.py 才是树莓派 arm 平台可用的版本。所以,最佳实践是:.ui 文件在开发机转换,.qrc 文件源文件同步到树莓派,在树莓派上本地转换。

6. 编写与测试你的第一个 PySide2 应用

环境都配好了,文件也准备好了,让我们写一个简单的程序来测试一下整个工作流是否畅通。在树莓派的项目目录下(pipenv shell 激活的环境中),创建一个 main.py 文件。

假设你已经按照上一节的方法,拥有了从开发机生成的 ui_mainwindow.py 和在树莓派生成的 resources_rc.pymain.py 的内容可以这样写:

import sys
import os

# 导入PySide2模块
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader

# 导入我们自己转换的界面文件
from ui_mainwindow import Ui_MainWindow
# 导入资源文件(确保是树莓派本地生成的)
import resources_rc

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        # 使用从.ui文件生成的类来设置界面
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # 这里可以连接信号槽,进行业务逻辑编写
        self.ui.pushButton.clicked.connect(self.on_button_clicked)

    def on_button_clicked(self):
        self.ui.label.setText("你好,树莓派!PySide2运行成功!")

if __name__ == "__main__":
    # 确保在高分屏上能有正确的缩放(可选)
    os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

这个例子使用了直接导入 ui_mainwindow.py 中自动生成类的方式。还有一种方式是使用 QUiLoader 动态加载 .ui 文件,但对于树莓派,由于没有 pyside2-uic 工具,我更推荐上面这种静态加载的方式,性能更好,也更清晰。

保存文件后,在终端里运行:

python3 main.py

如果一切配置正确,你应该能看到一个窗口弹出,上面有一个按钮和一个标签。点击按钮,标签的文字会改变。这就意味着你的 PySide2 开发环境在树莓派 armv7l 上完全配置成功了!

7. 虚拟环境日常使用与依赖管理

项目开发过程中,除了 PySide2,你肯定还需要安装其他纯 Python 的第三方库,比如 requests 发网络请求,pyserial 操作串口,matplotlib 画图表等等。这些库的安装,就应该完全在虚拟环境内部进行,使用 pipenv install 命令。

例如,安装 requests:

pipenv install requests

pipenv 会自动更新 PipfilePipfile.lock,记录精确的依赖版本。这比手动维护 requirements.txt 方便多了。

当你需要把项目迁移到另一台树莓派,或者分享给朋友时,只需要把项目目录下的 PipfilePipfile.lock 复制过去。在新的树莓派上,按照本文的步骤配置好系统和 PySide2 后,进入项目目录,运行:

pipenv install --ignore-pipfile

pipenv 会根据 Pipfile.lock 安装所有依赖库。而 PySide2 因为我们已经通过系统包安装,并且虚拟环境通过 --site-packages 共享了,所以不需要重复安装,完美解决了 arm 平台编译难题。

最后,日常开发中,记得用 pipenv shell 激活环境,或者直接用 pipenv run python3 your_script.py 来运行脚本。退出环境用 exit。要删除虚拟环境,可以在项目目录外执行 pipenv --rm

这套组合拳——pipenv + --site-packages + apt 安装 PySide2——是我在树莓派 arm32 架构上经过多次项目实践后总结出的最稳定、最省心的方案。它既保证了项目的独立性,又规避了 arm 平台复杂的编译问题,让你能专注于应用开发本身,而不是没完没了地折腾环境。希望这份详细的指南能帮你少走弯路,快速在树莓派上开启你的图形界面项目之旅。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐