Python调用C语言四种方式:ctypes、CFFI、Cython与原生扩展
做 AI 智能体项目做到一定体量你早晚会碰到一个坎Python 写起来是真的顺手但遇到计算密集的任务纯 Python 能把你急死。处理大数组、做哈希计算、解析二进制协议、批量跑向量距离这些活儿如果全用 Python 的循环去干慢得让人怀疑人生。我个人的习惯是把计算密集的部分交给 C 语言Python 只负责调度和胶水。这两年在做智能体工作流与自动化工具的性能优化时我反复用同一个思路今天就把 Python 调用 C 代码的四种主要方式一次性讲清楚ctypes、CFFI、Cython以及最底层的 Python/C API 原生扩展。这篇内容适合正在做智能体、自动化脚本、量化分析、算法工具的人尤其是那些被性能卡住、又不想引入太重框架的朋友。1. 四条技术路线先把全局看清楚1.1 为什么 Python 需要调用 C很多人对“Python 调用 C”有个误解以为只有写底层框架的人才需要。其实你每天都在用hashlib、zlib、sqlite3、json在 CPython 里部分核心是 C 实现标准库里一堆模块本来就是 C 扩展。也就是说CPython 这个解释器本身就提供了 Python 与 C 之间的完整桥接机制只是大多数人没有意识到自己一直在享受这个红利。真正需要主动调用 C 的场景通常有两个特征。一是性能瓶颈明显Python 的循环在遇到上亿次迭代时非常吃力因为每次操作都涉及动态类型检查、对象分配和引用计数。二是需要复用现成的 C/C 库比如某个加密算法、编解码器、数学计算库只有 C 版本或者团队之前用 C 写好了核心模块你不想用 Python 重写一遍。在 AI 智能体的工作流里这类场景特别常见例如读取嵌入式设备的二进制数据、对毫秒级延迟敏感的 token 化处理、批量计算 embedding 相似度等。还有一个现实层面的原因Python 生态已经足够庞大但 Python 自身从来不是“快”的语言。它的定位是“开发效率高”把性能敏感的部分下沉到 C本身就是 Python 社区过去三十年沉淀下来的标准玩法。理解这条路径等于给自己多了一把性能优化的钥匙。1.2 四种方式的本质差异先说结论四种方式没有绝对的优劣区别主要在两个维度——什么时候绑定 C 函数以及类型信息怎么传给 C。ctypes是运行时动态绑定Python 进程启动后它去加载一个.soLinux、.dllWindows或.dylibmacOS共享库通过libffi在运行时完成函数调用。优点是完全不用写 C 代码、不用编译任何包装层缺点是有一定的调用边界开销。CFFI走的是“声明式绑定”路线它更接近 C 的思维方式可以有两种模式一种像 ctypes 一样在运行时加载动态库ABI 模式另一种把 C 代码和 Python 绑定一起编译成扩展模块API 模式。API 模式比 ctypes 更接近底层性能更好。Cython的思路完全不同它不是“绑定 C”而是把 Python 代码本身编译成 C。你可以写一个带类型标注的.pyx文件它和 Python 语法高度兼容但允许声明cdef、cpdef来标注变量和函数的 C 类型最后生成 C 代码并编译成扩展模块。Python/C API是正统的 CPython 扩展开发方式直接用 C 语言写模块使用 CPython 提供的 API 操作 Python 对象包办引用计数、错误处理、GIL 等。这是性能天花板最高、对开发者要求也最高的一条路。1.3 一张表搞定选型方式是否需要编译 C 包装层学习成本调用开销最合适的场景ctypes不需要只需目标动态库低中等单次调用有固定开销快速调用现成的 C/C 库CFFI可编译也可不编译中API 模式较低需要类型安全、声明清晰的项目Cython需要中低把现成 Python 热函数编译提速Python/C API需要高最低完全可控长期维护的底层库、资源密集型模块选型逻辑很简单如果你是“临时接一个库”ctypes 最快如果你是“把自己写的 Python 代码提速”Cython 最顺手如果你在做团队级项目并且需要严格的 C 类型声明CFFI 更合适如果你要做一个要发布给全团队长期用的高性能扩展Python/C API 最踏实。2. 方式一ctypes最快上手的动态库调用2.1 先准备一个 C 共享库ctypes 的理念是“不需要你碰 C”但你手上得有一份编译好的动态库。为了演示我先写一个简单的 C 文件math_ops.c包含几个常用的函数整数加法、浮点加法、结构体距离计算、数组求和。#include math.h typedef struct { double x; double y; } Point; int add_int(int a, int b) { return a b; } double add_double(double a, double b) { return a b; } double point_distance(const Point *p1, const Point *p2) { double dx p1-x - p2-x; double dy p1-y - p2-y; return sqrt(dx * dx dy * dy); } double array_sum(double *arr, int n) { double s 0.0; for (int i 0; i n; i) { s arr[i]; } return s; }在 Linux 下编译成共享库gcc -shared -fPIC -o libmath_ops.so math_ops.c -lm这里有两个参数值得解释。-shared表示生成共享库-fPIC表示生成位置无关代码这是共享库能被加载到任意内存地址的必要条件。最后的-lm是链接数学库因为用了sqrt。如果在 macOS 上产物后缀是.dylib在 Windows 上需要用 MSVC 或 MinGW 编译成.dll加载路径符也要换成\\或os.path.join处理。2.2 用 ctypes 绑定函数C 库准备好之后Python 这边就非常轻松了import ctypes # 加载共享库Linux 默认用 CDLL lib ctypes.CDLL(./libmath_ops.so) # 关键先声明参数类型和返回值类型 lib.add_int.argtypes [ctypes.c_int, ctypes.c_int] lib.add_int.restype ctypes.c_int print(lib.add_int(3, 5)) # 8 lib.add_double.argtypes [ctypes.c_double, ctypes.c_double] lib.add_double.restype ctypes.c_double print(lib.add_double(1.5, 2.25)) # 3.75很多刚接触 ctypes 的人会踩同一个坑不写argtypes和restype也能调用成功但 C 函数的返回值默认按int处理指针在 64 位系统上是 8 字节int 只有 4 字节一旦函数返回指针或者double结果就会变成乱码甚至直接段错误。所以我把第一条经验写在这里动态库一加载先把所有要调的函数参数类型和返回类型声明完再开始调。2.3 结构体、数组、指针和回调ctypes 对结构体和数组的映射也很自然直接定义 Python 类来模拟 C 结构体class Point(ctypes.Structure): _fields_ [ (x, ctypes.c_double), (y, ctypes.c_double), ] lib.point_distance.argtypes [ctypes.POINTER(Point), ctypes.POINTER(Point)] lib.point_distance.restype ctypes.c_double p1 Point(0.0, 0.0) p2 Point(3.0, 4.0) # byref 相当于 C 里的 取地址传给指针参数 print(lib.point_distance(ctypes.byref(p1), ctypes.byref(p2))) # 5.0数组求和那边需要先构造一个 ctypes 数组对象lib.array_sum.argtypes [ctypes.POINTER(ctypes.c_double), ctypes.c_int] lib.array_sum.restype ctypes.c_double # 构造 C 数组 arr (ctypes.c_double * 5)(1.0, 2.0, 3.0, 4.0, 5.0) print(lib.array_sum(arr, 5)) # 15.0如果 C 函数要回调 Python 函数用CFUNCTYPE声明回调类型CALLBACK_FUNC ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int) CALLBACK_FUNC def my_callback(x): return x * 2 # 假设 C 库里有 apply_callback(fn, x)把 my_callback 传进去这里有一个非常重要的细节ctypes 在调用普通共享库函数CDLL时会临时释放 GIL所以多线程环境下不会把整个 Python 进程卡死。但如果你用PyDLL加载库GIL 不会释放调用期间其他 Python 线程全部被阻塞。需要长时间执行 C 计算时优先用CDLL或者自己控制好线程策略。另一个容易出的问题是对象生命周期。Point这样的 ctypes 对象如果被 Python 的垃圾回收提前回收而 C 库里还留着指针之后再调用就会产生悬空指针表现为莫名其妙的崩溃。所以在和 C 交互期间一定要让关键对象在 Python 侧保持引用比如挂在一个模块级变量或者明确的容器里。3. 方式二CFFI声明式绑定与两种编译模式3.1 ABI 模式和 API 模式到底差在哪CFFI 是我在实际项目中用得越来越多的一个库它的定位很明确比 ctypes 更安全、更像 C同时比手写 Python/C API 省事得多。CFFI 支持两种模式很多人第一次接触会被绕晕这里直接讲透。ABIApplication Binary Interface模式用ffi.dlopen加载动态库效果和 ctypes 类似运行时绑定不需要编译。区别在于 cdef 声明写得更标准而且 CFFI 对类型的检查更严格错误信息也更人性化。APIApplication Programming Interface模式则用ffi.set_sourceffi.compile生成一个真正的 CPython 扩展模块编译期绑定。这个模式的好处是类型信息完整调用开销更接近原生扩展还支持在编译期嵌入额外的 C 代码。可以说 API 模式是在“ctypes 的方便”和“原生扩展的性能”之间取了一个折中。我个人的判断是如果你只调一两个函数ctypes 够了如果调用的 C 接口比较多、团队还要长期维护那就直接用 CFFI 的 API 模式代码可读性和健壮性都好很多。3.2 CFFI 实战声明、编译、调用先安装pip install cffi最简单的 ABI 模式用法from cffi import FFI ffi FFI() # cdef 里写的是纯 C 声明编译器会拿来生成正确的包装 ffi.cdef( int add_int(int a, int b); double add_double(double a, double b); ) lib ffi.dlopen(./libmath_ops.so) print(lib.add_int(17, 25)) # 42 print(lib.add_double(1.5, 2.5)) # 4.0如果要用 API 模式写一个构建脚本# build_math_cffi.py from cffi import FFI ffi FFI() ffi.cdef( double add_double(double a, double b); ) # set_source 的第一个参数是生成的扩展模块名第二个参数是嵌入的 C 代码 ffi.set_source(_math_cffi, double add_double(double a, double b) { return a b; } ) if __name__ __main__: ffi.compile(verboseTrue)运行python build_math_cffi.py之后目录里会出现编译好的_math_cffi.cpython-xx-xxx.so然后直接在 Python 里导入使用import _math_cffi print(_math_cffi.lib.add_double(10.5, 21.5)) # 32.0CFFI 在处理结构体和数组上的体验也比 ctypes 舒服因为它照搬 C 语法from cffi import FFI ffi FFI() ffi.cdef( typedef struct { double x; double y; } Point; double point_distance(const Point *p1, const Point *p2); ) lib ffi.dlopen(./libmath_ops.so) p1 ffi.new(Point *, {x: 0.0, y: 0.0}) p2 ffi.new(Point *, {x: 3.0, y: 4.0}) print(lib.point_distance(p1, p2)) # 5.0ffi.new一次性把内存分配和类型声明都做了返回的是一个可以直接传给 C 函数的指针对象不需要像 ctypes 那样写byref。数组也是同理ffi.new(double[100])就得到一块可以传给 C 的连续内存。这种“书写方式和 C 一致”的设计减少了我脑内“翻译”的负担。CFFI 的坑主要在编译环境上API 模式需要系统里有 C 编译器Windows 上推荐 Visual Studio 的 C 工具链Linux 上确保python3-dev和build-essential都装了。另外cdef 里的声明必须和实际库的 ABI 完全一致一旦函数签名不对运行时会表现得很诡异而且这种错误不会在编译期发现需要自己用nm -D之类的工具去核对导出的符号。4. 方式三Cython让 Python 代码自己变成 C4.1 从一个 .pyx 文件开始Cython 是我处理“Python 算法本身太慢”时的首选方案。它的核心卖点是你写的东西和 Python 语法高度重合不需要单独维护 C 文件只需要给热点变量加上 C 类型声明然后交给编译器生成 C 代码。看一个最简单的例子。假设我想写一个高效的数组求和函数先用 Python 风格写.pyx文件# math_fast.pyx # cython: language_level3 cpdef double cy_sum(double[:] arr): cdef int n arr.shape[0] cdef int i cdef double s 0.0 with nogil: for i in range(n): s arr[i] return s这里的cpdef表示这个函数既能在 Python 调用也能在 Cython 的内部代码里以 C 函数形式调用。double[:]是 typed memoryview可以直接接收array.array、numpy.ndarray和其他缓存了缓冲接口的序列。with nogil是整段代码的关键它告诉 Cython这段循环里没有 Python 对象操作可以释放全局锁允许并行执行。对应的setup.pyfrom setuptools import setup from Cython.Build import cythonize setup( namemath_fast, ext_modulescythonize( math_fast.pyx, compiler_directives{language_level: 3}, ), )编译python setup.py build_ext --inplace然后就能像导入普通 Python 模块一样使用import array import math_fast arr array.array(d, range(1000)) print(math_fast.cy_sum(arr)) # 499500.0如果传入的是 numpy 数组同样可以直接用不需要任何转换。4.2 怎么判断提速有没有生效Cython 最容易出现的问题不是报错而是“编译成功但根本没提速”。原因通常是核心循环里还有 Python 对象操作Cython 编译器没法把它变成纯 C 代码只能悄悄退回解释器调用。正确做法是激活 Cython 的代码注析功能cython -a math_fast.pyx它会生成一个 HTML 页面里面每一行代码都有颜色标注白色表示编译成了纯 C黄色表示还有 Python 交互黄色越深说明 Python 调用越多。你在浏览器里打开看一遍就能精确知道瓶颈在哪一行。实际项目中我见过不少“写了 Cython 但还是慢”的案例最后定位到的问题都是循环里不小心用了list.append、字符串格式化这些 Python 操作把它们挪到nogil块之外或者换成 C 类型速度立刻不一样。Cython 还支持“纯 Python 模式”你不写.pyx直接给.py文件加类型注解然后通过cythonize编译。这对从已有 Python 代码迁移非常友好可以一行一行把性能热点变成 C不需要模块整体搬迁。不过纯 Python 模式能标注的类型种类没有.pyx丰富极端性能优化还是建议用.pyx。有一个细节Cython 生成的 C 代码默认带着-O2等优化参数在编译因此本地构建时间可能有几十秒这是正常的。如果项目很小可以考虑把 Cython 产物提交到构建缓存里或者用ccache加速重复构建。5. 方式四Python/C API写一个真正的原生扩展5.1 从零写一个 CPython 扩展模块前面三种方式都是在“调用别人的 C”而 Python/C API 是“在 C 世界里实现一个 Python 模块”。这个方式的优点是完全可控缺点也很明显你不仅要懂 C还要懂 CPython 的对象模型、引用计数、错误处理和 GIL 规则。下面我用一个最简单的例子说明全流程。写一个 C 文件csum.c提供一个csum.array_sum函数接收一个可迭代对象返回其中所有数值之和。#define PY_SSIZE_T_CLEAN #include Python.h static PyObject * array_sum(PyObject *self, PyObject *args) { PyObject *seq; PyObject *iter; PyObject *item; double total 0.0; // 解析参数O 表示接收一个 Python 对象 if (!PyArg_ParseTuple(args, O, seq)) { return NULL; } iter PyObject_GetIter(seq); if (iter NULL) { return NULL; } while ((item PyIter_Next(iter)) ! NULL) { double v PyFloat_AsDouble(item); Py_DECREF(item); if (v -1.0 PyErr_Occurred()) { Py_DECREF(iter); return NULL; } total v; } Py_DECREF(iter); if (PyErr_Occurred()) { return NULL; } return PyFloat_FromDouble(total); } static PyMethodDef CSumMethods[] { {array_sum, array_sum, METH_VARARGS, 计算可迭代对象中所有数值之和}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef csummodule { PyModuleDef_HEAD_INIT, csum, 演示用 C 实现的扩展模块, -1, CSumMethods }; PyMODINIT_FUNC PyInit_csum(void) { return PyModule_Create(csummodule); }配套的setup.pyfrom setuptools import setup, Extension ext Extension( csum, sources[csum.c], ) setup( namecsum, ext_modules[ext], )编译和导入python setup.py build_ext --inplaceimport csum print(csum.array_sum([1.0, 2.0, 3.0, 4.0])) # 10.0这个例子虽然简单但已经把 CPython 扩展的核心要素全部走了一遍Python.h必须是最早引入的头文件之一参数解析用PyArg_ParseTuple函数表用PyMethodDef注册模块结构体用PyModuleDef描述模块初始化函数必须命名为PyInit_csum和扩展模块名严格对应。5.2 引用计数、GIL 和错误处理务必谨慎在 Python/C API 里程序员的每一行代码都要顾及三件事谁拥有这个对象的引用、谁负责释放、出错时怎么传播异常。以PyFloat_AsDouble(item)为例它返回的是double值item的引用依然在循环里我们调完立刻Py_DECREF(item)防止累积引用泄漏。如果忘记这一步每次调用都会泄漏一个对象长时间运行的模块内存会一路涨上去。反过来如果提前释放了还需要使用的对象那就是悬空指针崩溃几乎无法排查。错误处理的约定是绝大多数 Py* 函数出错时返回 NULL 或 -1同时设置一个异常。C 函数必须把这个异常状态传递回解释器也就是立刻return NULL一旦你自己吞掉异常后面的行为就不可预测了。上面的例子我特意写了PyErr_Occurred()检查就是防止迭代过程中出现异常时循环继续误跑。GIL 方面如果你的 C 代码内部有一段纯计算的耗时逻辑可以主动释放 GIL让其他 Python 线程有机会运行static PyObject * busy_wait(PyObject *self, PyObject *args) { double seconds; if (!PyArg_ParseTuple(args, d, seconds)) { return NULL; } Py_BEGIN_ALLOW_THREADS // 这里运行纯 C 的耗时逻辑比如长时间循环、等待 IO Py_END_ALLOW_THREADS Py_RETURN_NONE; }但要特别记住Py_BEGIN_ALLOW_THREADS和Py_END_ALLOW_THREADS之间绝对不能调用任何 Python API因为那时候你没有持有 GIL操作 Python 对象是未定义行为。这条规则也和前面 ctypes 的“CDLL 默认释放 GIL”形成了对照只要跨界调用 C都需要想清楚锁的问题。Python/C API 的学习曲线是最陡的但收益也最实在。如果将来要发布一个给团队长期使用的库或者需要精细控制内存布局、多线程并发、自定义对象类型用这套方式才是正经路线。其他三种方式本质上都是在它头上套的“省事层”。6. 常见问题和排坑技巧实录6.1 高频问题速查表症状可能原因处理建议一调用就段错误SegFaultargtypes/restype没声明指针被截断先补齐所有函数的类型声明返回值永远是 0 或者乱码函数返回double或指针但restype默认是int设置正确的restype指针用c_void_p或对应类型ImportError: undefined symbolC 库编译时漏链接依赖或依赖库不在搜索路径用nm -D检查导出符号用ldd检查依赖必要时设LD_LIBRARY_PATH提示Python.h找不到只装了运行环境没装开发头文件Ubuntu/Debian 装python3-devmacOS 装 Command Line Toolsgcc: command not found缺编译工具链Linux 装build-essentialWindows 装 Visual Studio C 环境Cython 编译成功但没提速核心循环里残留 Python 对象操作用cython -a生成注析 HTML找出黄色行并改写C 线程里回调 Python 函数崩溃回调没持有 GIL回调入口用PyGILState_Ensure/PyGILState_Release包住函数调用本身很慢单次调用有固定边界开销循环里频繁调用改成批量接口把数组一次性传给 C在 C 内部循环6.2 到底该选哪种我的实践经验先说我自己目前最顺手的组合临时接一个已有的 C/C 库用 ctypes把自己写的 Python 热函数提速用 CythonCFFI 适合团队协作和接口较多的场景Python/C API 只在维护真正底层的扩展时才碰。还有一个很多人会忽略的思路如果 C 程序本身已经是一个命令行工具用subprocess调用它也是完全可行的特别是频率低、参数少、只需要解析标准输出的任务。它的缺点是每次调用都要拉起一个进程开销很大不适合高频循环。我把它当成第零种方案用来应急是可以的。选型前一定先做的事是性能剖析。很多来找我优化的朋友一上来就说“Python 太慢我要换 C”结果我用 profiler 跑一遍发现瓶颈根本不在算法而在不必要的重复计算、日志同步、或者循环里频繁做字符串拼接。把这类问题解决掉速度可能已经提升了十倍根本不需要动 C。如果 profile 之后确认热点确实在某个计算密集的循环里再上 C事半功倍。另外提醒一句不要追求“处处都用 C”。每次顶层调用的边界开销大约在数百纳秒到微秒级别如果循环每轮都跨边界一次总开销会非常可观。好的做法是把要批量计算的部分设计成一个数组接口让 C 函数一次处理一大块数据而不是在 Python 循环里反复调用 C 函数。最后说点个人体会。我在真实项目里最珍惜的能力不是会写多漂亮的 C 扩展而是能准确判断“这一段到底该不该下沉到 C”。AI 智能体这类应用的特点恰好是思维链、任务编排、工具调用等逻辑复杂多变非常适合 Python 来写但底层的计算、解析、加解密、向量运算又对性能敏感非常适合 C 来扛。把这两层用今天讲的四种桥接方式稳定地连起来你手里的系统就会既有 Python 的灵活又有 C 的肌肉。还有一个我踩过几次坑之后养成的习惯所有涉及 C 调用的代码都先在最小环境里写一个 shesh测试单独验证数据能正确往返再集成进业务模块。因为一旦有段错误核心文件往往是查不到根因的而最小复现是最快的定位路径。这篇内容如果对你有帮助后续我可以把 Cython 的纯 Python 模式迁移技巧和 Python/C API 的模块打包发布各拆成一篇配上真实项目的性能基准实测。实践出真知欢迎交流你的用法。

相关新闻

Python爬虫实战:抓取第一财经热点专题并实现热度排序

Python爬虫实战:抓取第一财经热点专题并实现热度排序

做爬虫这事儿有个逃不开的规律:练手数据集要好找、要够干净,还要能讲出点故事。第一财经的热点专题大盘就是我一直推荐的入门级数据源之一。用Python爬虫把这些专题的标题、热度、更新时间、详情链接抓下来,再按热度排个序,基本就…

2026/10/3 15:06:22 阅读更多 →
用堆栈和组件状态,把静态组件变成响应式UI活组件

用堆栈和组件状态,把静态组件变成响应式UI活组件

做 UI 设计这几年,我最怕听到的一句话就是“这里再加一行文案”。表面只是一句话,背后却是静态组件带来的连环噩梦:卡片被撑高,按钮要往下挪,旁边几个画板里的同一张卡片全得手动改一遍。Adobe XD 里的“静态组件”&am…

2026/10/3 15:06:22 阅读更多 →
云南土壤shape文件标准化生产与校验避坑指南

云南土壤shape文件标准化生产与校验避坑指南

简介:这是一份云南省土壤类型空间分布数据,以标准shape文件交付,面向GIS从业者、土壤学研究人员及自然资源规划人员,解决省级尺度土壤类型底图获取与分类体系对接问题。数据基于1:400万中国土壤图分类系统编码,三位数字…

2026/10/3 15:05:21 阅读更多 →

最新新闻

用GPU加速Elasticsearch向量索引:cuVS实战1.38亿向量10分钟建索引

用GPU加速Elasticsearch向量索引:cuVS实战1.38亿向量10分钟建索引

直接开始分享。作为一个长期跟 Elasticsearch 和向量检索打交道的工程师,我最近做了一组实验:用 NVIDIA cuVS 给 Elasticsearch 做 GPU 加速的向量索引,目标是把“1.38 亿个向量”的建索引时间压在 10 分钟以内。实测下来,结果让我…

2026/10/3 15:43:22 阅读更多 →
抖音视频搜索数据采集实战:基于Playwright的爬虫方案解析

抖音视频搜索数据采集实战:基于Playwright的爬虫方案解析

做自媒体账号运营和竞品分析,绕不开抖音这个流量池。我自己的团队在做内容选题和热点追踪时,经常需要批量获取某个关键词下的视频数据——标题、作者、点赞量、评论数这些公开信息。一开始手工复制粘贴,几十条还能忍,几百条就开始…

2026/10/3 15:43:22 阅读更多 →
Unity求职Demo制作指南:从功能闭环到面试展示

Unity求职Demo制作指南:从功能闭环到面试展示

“27 届 Unity 求职 demo”这个标题,今年校招场景里出现的频率不低。很多同学手里的 Unity 作品还停留在“跟着教程做出来的 MMO 打怪 Demo”,或者只有一段没头没尾的游戏录屏。到了面试官面前,被问到“这个项目里你最满意的功能是什么”“有…

2026/10/3 15:43:22 阅读更多 →
Python贪吃蛇实战:完整源码与Pygame游戏开发入门

Python贪吃蛇实战:完整源码与Pygame游戏开发入门

如果你已经学完了 Python 的基础语法,正处在“教程都看懂了,但不知道下一步该做什么”的阶段,那么贪吃蛇这个项目非常值得停下来认真做一遍。它看起来像是一个怀旧小游戏,但背后涉及的 Python 基础、事件处理、数据结构、碰撞检测…

2026/10/3 15:43:22 阅读更多 →
从零搭建openrig模块化支架:铝型材DIY装备平台全解析

从零搭建openrig模块化支架:铝型材DIY装备平台全解析

1. openrig到底在解决什么问题1.1 “rig”这个词,在玩家圈里到底指什么要是你在硬件社区、模拟器论坛或者DIY群里泡过一阵子,肯定见过“rig”这个说法。有人晒“My first rig”,配图是一套方向盘加支架;有人说“I just upgraded m…

2026/10/3 15:43:22 阅读更多 →
AI实时压缩与边缘多模态对齐技术实战指南

AI实时压缩与边缘多模态对齐技术实战指南

1. 这不是一份新闻简报,而是一份AI行业动态的“操作手册”“AI 日报(2026年9月26日)”——看到这个标题,很多人第一反应是点开扫一眼热点,划两下就关掉。但如果你真这么做了,大概率会错过过去24小时里真正影…

2026/10/3 15:42:21 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill:导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候,我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟,一上机全露馅。后来自己从被面的人变成面别人的人,才慢慢摸清楚:Linux面试题考的根本不是答案本身,而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介:本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南,聚焦SAP生产预留核心业务场景,系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →