
1. 为什么要在树莓派上同时搞定 Python 和 C 两套环境很多人拿到树莓派的第一反应是把它当成一台“迷你 Linux 主机”装个系统、连上屏幕、打开终端然后就开始琢磨我到底该用 Python 还是 C 来写东西这个问题其实问反了。树莓派最有意思的地方恰恰是它同时把 Python 和 C 这两条路都铺好了而且两条路之间还能互相打通。你完全可以在同一个项目里用 Python 做快速原型和逻辑调度用 C 去啃那些对时序、内存、响应速度有硬要求的活。我自己的习惯是只要涉及 GPIO 时序、传感器高频采样、或者需要跟底层寄存器打交道优先考虑 C而数据处理、网络通信、脚本自动化、快速验证想法Python 就是首选。树莓派官方系统默认就带了 Python但 C 环境往往需要你手动补几块拼图尤其是编译工具链和开发头文件。这一篇就把这两套环境的安装、验证、以及它们之间如何协作从头到尾捋一遍。这篇文章适合刚接触树莓派、想认真做点硬件交互项目的人也适合已经会用 Python 但想往底层再走一步的开发者。我会把每一步的命令、参数含义、踩过的坑都写清楚你照着做基本不会卡住。核心关键词就三个树莓派、Python 环境、C 编译环境。下面直接进入正题。2. 动手前的系统状态确认与基础准备2.1 先确认你的系统版本和架构在装任何东西之前先搞清楚自己手里这台树莓派跑的是什么系统。不同版本的官方系统包管理器和默认软件源会有差异装错命令轻则报错重则把依赖搞乱。打开终端执行cat /etc/os-release uname -m/etc/os-release会告诉你系统代号比如 bookworm、bullseye 这些。uname -m看架构常见的是aarch6464 位或armv7l32 位。这两个信息很关键因为后面装 C 工具链时某些包名会跟架构挂钩。我遇到过有人拿着 64 位系统去装 32 位的交叉编译库结果编译出来的二进制跑不起来排查半天才发现是架构对不上。所以这一步别偷懒花十秒钟确认一下后面省半小时。2.2 更新软件源和已装包树莓派官方镜像出厂时的软件源索引往往不是最新的直接装东西可能遇到“找不到包”或者“版本冲突”。先做一次全面更新sudo apt update sudo apt upgrade -yapt update是刷新软件包索引apt upgrade是把已安装的包升到最新。这里有个经验如果你用的是比较老的系统版本upgrade可能会拉下来一大堆更新耗时较长建议接好稳定电源再操作别中途断电。树莓派的 SD 卡如果质量一般写入过程中断电有概率导致文件系统损坏这个坑我踩过后来换了好点的卡就再没出过事。提示更新前可以用df -h看一眼根分区剩余空间建议至少留 1GB 以上否则升级过程可能因为空间不足失败。2.3 检查 Python 是否已经就位官方系统通常预装了 Python 3但版本可能偏旧。先看看现状python3 --version which python3 pip3 --version如果python3 --version能正常输出比如Python 3.11.x说明解释器已经有了。pip3是包管理工具有时候系统只带了 Python 但没带 pip那就需要单独补。which python3是确认它到底装在哪个路径下方便后面排查多版本共存的问题。这里要提醒一句不要轻易去动系统自带的 Python。Linux 系统里很多工具依赖系统 Python你如果强行把系统 Python 升级或者替换可能导致 apt 本身都跑不起来。正确做法是保留系统 Python需要新版本时用虚拟环境或者单独安装。3. Python 环境的完整安装与配置3.1 安装 Python 3 解释器和 pip虽然系统可能自带 Python但为了确保 pip 和 venv 这些配套工具齐全还是走一遍安装命令sudo apt install -y python3 python3-pip python3-venv python3-dev逐个说下这几个包的作用。python3是解释器本体python3-pip是包安装工具python3-venv用来创建虚拟环境这个非常重要后面会展开python3-dev包含开发头文件如果你要编译 Python 的 C 扩展模块或者用 C 调用 Python这个包必不可少。装完之后验证一下python3 --version pip3 --version如果 pip 版本提示较旧可以升级它自己python3 -m pip install --upgrade pip注意这里用的是python3 -m pip而不是直接pip3这样能确保 pip 装到当前 Python 对应的环境里避免多版本时装错地方。3.2 配置国内软件源加速安装默认的 pip 源在国外装大包的时候速度可能很慢甚至超时。换成国内镜像源会顺畅很多。有两种做法一种是临时指定一种是永久配置。临时用某个源装包pip3 install 包名 -i https://pypi.tuna.tsinghua.edu.cn/simple永久配置的话创建或编辑配置文件mkdir -p ~/.config/pip nano ~/.config/pip/pip.conf写入以下内容[global] index-url https://pypi.tuna.tsinghua.edu.cn/simple timeout 60timeout设成 60 秒是防止网络波动时过早中断。配置好之后以后所有 pip 安装都会走这个源。我实测下来换源之后装 numpy、opencv 这类大包速度能从龟速变成正常宽带水平。注意镜像源偶尔会有同步延迟如果发现某个包版本比官方旧可以临时用-i参数指定官方源装一次装完再切回来。3.3 虚拟环境的创建与使用这是 Python 环境管理里最值得养成的习惯。系统 Python 是公共资源你直接往里装包装多了会污染全局环境不同项目依赖冲突时非常难处理。虚拟环境就是给每个项目单独开一个“隔离房间”。创建虚拟环境python3 -m venv myproject_env这会在当前目录下生成一个myproject_env文件夹里面是一套独立的 Python 环境。激活它source myproject_env/bin/activate激活后终端提示符前面会出现(myproject_env)字样这时候你用的python和pip都是这个环境里的装什么都不会影响系统。退出用deactivate我一般会在项目根目录下建一个venv文件夹然后把它加到.gitignore里这样代码仓库干净别人克隆下来自己重建环境就行。3.4 验证 Python 环境是否可用装完总得跑个东西确认一下。先看基础功能python3 -c print(hello raspberry)再装一个常用库测试 pip 是否正常pip3 install requests python3 -c import requests; print(requests.__version__)如果两行都能正常输出说明 Python 解释器、pip、网络源这条链路全通了。到这一步Python 环境就算齐活了。4. C 语言编译环境的搭建与验证4.1 安装 GCC 和 G 工具链树莓派官方系统里C 编译器通常不是默认全装的需要手动补。核心包是build-essential它是一组工具的集合sudo apt install -y build-essential这个包里包含gccC 编译器、gC 编译器、make构建工具、libc6-dev标准 C 库头文件等。为什么推荐直接装build-essential而不是单独装 gcc因为单独装 gcc 往往缺头文件编译时会出现“找不到 stdio.h”这种让人抓狂的错误而build-essential一次性把依赖都解决了。装完验证gcc --version g --version make --version三条命令都能输出版本号说明工具链就位。4.2 安装调试器和常用开发库光有编译器还不够实际开发中调试器几乎离不开。装 gdbsudo apt install -y gdb如果你要做硬件相关的 C 开发比如操作 GPIO、I2C、SPI还需要对应的开发库sudo apt install -y libgpiod-devlibgpiod-dev是现在官方推荐的 GPIO 操作库比老的 sysfs 方式更规范。另外像i2c-tools、spi-tools这些调试工具也建议装上方便你扫描总线上挂了哪些设备。4.3 写第一个 C 程序并编译建一个测试文件hello.c#include stdio.h int main(void) { printf(Hello from C on Raspberry Pi\n); return 0; }编译gcc hello.c -o hello运行./hello看到输出就说明 C 环境完全正常。这里解释下编译命令gcc是编译器hello.c是源文件-o hello指定输出文件名为hello。如果不加-o默认会生成a.out。4.4 用 Makefile 管理多文件编译单文件编译直接敲 gcc 没问题但项目一大文件多了每次都手敲命令不现实。这时候用 Makefile。举个简单例子CC gcc CFLAGS -Wall -O2 TARGET app OBJS main.o utils.o $(TARGET): $(OBJS) $(CC) $(OBJS) -o $(TARGET) %.o: %.c $(CC) $(CFLAGS) -c $ -o $ clean: rm -f $(OBJS) $(TARGET)CFLAGS里的-Wall是打开所有警告-O2是二级优化。我强烈建议开发阶段始终开着-Wall它能帮你提前发现很多潜在 bug比如未初始化变量、类型不匹配。很多人嫌警告烦结果上线后出问题才回头查得不偿失。5. Python 与 C 混合编程的衔接要点5.1 为什么需要让两者协作单独用 Python 或单独用 C 都能干活但有些场景下混合使用才是最优解。比如你有一个对时间精度要求很高的传感器读取逻辑用 C 写效率高但上层的数据分析、可视化、网络上传用 Python 写起来快得多。这时候就需要让 C 和 Python 互相调用。5.2 用 ctypes 调用 C 动态库最轻量的方式是把 C 代码编译成动态库然后用 Python 的ctypes模块加载。先写 C 代码mylib.cint add(int a, int b) { return a b; }编译成动态库gcc -shared -fPIC -o libmylib.so mylib.c-shared表示生成动态库-fPIC表示生成位置无关代码这两个参数缺一不可。然后在 Python 里import ctypes lib ctypes.CDLL(./libmylib.so) result lib.add(3, 4) print(result)这种方式不用装额外东西适合简单函数调用。但要注意参数类型和返回值类型默认是 int如果涉及指针、结构体需要显式声明argtypes和restype否则容易出内存错误。5.3 用 Python C API 做深度集成如果 C 和 Python 之间要传复杂数据结构或者 C 代码需要回调 Python 函数那就得用 Python C API。这需要python3-dev包提供的头文件。一个最小示例#include Python.h static PyObject* say_hello(PyObject* self, PyObject* args) { printf(Hello from C extension\n); Py_RETURN_NONE; } static PyMethodDef Methods[] { {say_hello, say_hello, METH_NOARGS, print hello}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef module { PyModuleDef_HEAD_INIT, myext, NULL, -1, Methods }; PyMODINIT_FUNC PyInit_myext(void) { return PyModule_Create(module); }编译时需要指定 Python 的头文件路径通常用python3-config来获取gcc -shared -fPIC $(python3-config --includes) myext.c -o myext.so这种方式功能强但代码量大适合对性能要求极高的场景。日常项目里ctypes 已经能覆盖八成需求。6. 常见问题排查与避坑经验6.1 安装类问题速查表问题现象可能原因解决办法pip3: command not found没装 pipsudo apt install python3-pipgcc: command not found没装编译器sudo apt install build-essential编译报stdio.h: No such file缺开发头文件装libc6-dev或直接装build-essentialpip 安装超时默认源太慢换国内镜像源虚拟环境激活失败路径写错或没装 venv确认python3-venv已安装用绝对路径激活动态库加载报cannot open shared object file路径不对用绝对路径或设置LD_LIBRARY_PATH6.2 几个我踩过的坑第一个坑是权限问题。很多人习惯所有命令前面加sudo结果用sudo pip3 install把包装到了系统目录后来在虚拟环境里怎么都 import 不到。记住pip 安装永远不要加 sudo除非你明确知道自己在干什么。第二个坑是 Python 版本混乱。系统里可能同时存在python、python3、python3.9、python3.11多个入口pip3对应的可能是其中一个。最稳妥的方式是始终用python3 -m pip来装包这样 pip 和 python 一定是配套的。第三个坑是编译优化过头。有人为了追求性能直接上-O3结果某些依赖浮点精度的计算出现偏差。一般项目-O2足够了除非你做过基准测试确认-O3有收益且不引入问题。6.3 环境备份与迁移建议环境配好之后建议做一次备份。Python 这边用pip3 freeze requirements.txt导出依赖列表换机器时pip3 install -r requirements.txt就能重建。C 这边把 Makefile 和源码管理好就行工具链本身用 apt 重装很快。如果你用的是 SD 卡系统建议定期用dd或者官方工具做整卡镜像备份。我有一次 SD 卡突然挂掉好在之前备份过换张卡烧回去十分钟就恢复了。硬件项目最怕环境丢失这个习惯能救命。7. 我个人的一些实操体会Python 和 C 这两套环境在树莓派上其实是互补的不是二选一的关系。我现在的习惯是项目初期用 Python 快速验证逻辑等核心算法稳定了把性能瓶颈部分用 C 重写再通过 ctypes 接回去。这样开发效率和质量都能兼顾。另外装环境这件事看起来简单但细节特别多。我的建议是每装完一个组件就立刻验证别等全部装完再一起测否则出问题时你根本不知道是哪一步埋的雷。还有命令里的每个参数最好都搞懂它的含义而不是复制粘贴了事这样下次遇到变体场景你才能自己调整。最后分享一个小技巧如果你不确定某个包装了没有可以用dpkg -l | grep 包名查比重新装一遍再看好得多。环境这东西配一次理顺了后面就能安心写代码了。