在Python中调用C语言代码和Linux命令是常见的开发需求,尤其在需要高性能系统操作或复用现有C库时,本文将详细介绍实现方式、注意事项及最佳实践,帮助开发者高效整合不同语言和系统资源。

Python调用C语言代码的方法
Python与C语言的交互主要通过以下三种方式实现,每种方式适用于不同场景:
使用ctypes库调用C动态库
ctypes是Python内置的库,无需额外安装,适合调用简单的C函数,基本步骤包括:
- 编译C代码为共享库(.so文件)
- 在Python中使用ctypes加载并调用函数
示例流程:
// add.c
int add(int a, int b) {
return a + b;
}编译命令:

gcc -shared -fPIC -o libadd.so add.c
Python调用代码:
from ctypes import CDLL, c_int
lib = CDLL('./libadd.so')
result = lib.add(c_int(3), c_int(5))
print(result) # 输出: 8注意事项:
- 需处理数据类型映射(如c_int对应C的int)
- 复杂结构体需定义对应的ctype类
- 错误处理可通过
get_last_error()获取系统错误码
使用CFFI(C Foreign Function Interface)
CFFI提供更强大的接口支持,适合复杂场景,需安装cffi包,支持两种API:
- ABI模式:直接编译后的二进制接口(类似ctypes)
- API模式:从C头文件生成接口声明
API模式示例:

from cffi import FFI
ffi = FFI()
ffi.cdef("""
int add(int a, int b);
""")
lib = ffi.dlopen('./libadd.so')
result = lib.add(3, 5)
print(result) # 输出: 8优势:
- 支持复杂结构体和回调函数
- 可自动生成接口声明文件
- 性能优于ctypes
使用Python C扩展
通过编写C扩展模块,将C代码编译为Python可导入的模块,适合需要深度集成或高性能计算的场景。
步骤:
- 创建
module.c文件实现模块 - 编写
setup.py配置编译选项 - 使用
python setup.py build_ext --inplace编译
示例代码:
// module.c
static PyObject *add(PyObject *self, PyObject *args) {
int a, b;
if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
return NULL;
}
return PyLong_FromLong(a + b);
}
static PyMethodDef methods[] = {
{"add", add, METH_VARARGS, "Add two integers"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"mymath",
NULL,
-1,
methods
};
PyMODINIT_FUNC PyInit_mymath(void) {
return PyModule_Create(&module);
}setup.py
from setuptools import setup
from pybind11.setup_helpers import Pybind11Extension
ext = Pybind11Extension("mymath", sources=["module.c"])
setup(ext_modules=[ext])Python调用Linux命令的方法
Python执行Linux命令主要通过以下方式实现,需注意安全性和权限问题:
使用subprocess模块(推荐)
subprocess是官方推荐的跨平台命令执行模块,功能强大且灵活。
基本用法:
import subprocess
# 执行简单命令
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)
# 超时控制
try:
subprocess.run(['sleep', '10'], timeout=5)
except subprocess.TimeoutExpired:
print("命令执行超时")高级特性:
- 管道操作:
subprocess.Popen可构建命令管道 - 环境变量传递:通过
env参数自定义环境 - 安全执行:使用
shell=False避免命令注入
使用os.system(已不推荐)
简单但功能有限,且不推荐用于生产环境:
import os
os.system('ls -l') # 直接输出到终端使用commands模块(Python 3.11已移除)
旧版Python提供的接口,已被subprocess替代。
性能与安全对比
| 方法 | 性能 | 安全性 | 适用场景 |
|---|---|---|---|
| ctypes | 中 | 中 | 简单C函数调用 |
| CFFI | 高 | 高 | 复杂C接口集成 |
| Python C扩展 | 最高 | 高 | 高性能计算模块开发 |
| subprocess | 低 | 高 | 系统命令执行 |
| os.system | 低 | 低 | 简单命令(不推荐) |
最佳实践建议
C语言调用:
- 优先使用CFFI处理复杂接口
- 避免频繁的小函数调用,考虑批量处理
- 使用GIL释放机制(如
Py_BEGIN_ALLOW_THREADS)
命令执行:
- 始终使用
subprocess.run并设置timeout - 对用户输入进行严格过滤,避免命令注入
- 捕获并处理
CalledProcessError异常
- 始终使用
资源管理:
- 及时关闭文件描述符和子进程
- 使用上下文管理器(
with语句)管理资源
相关问答FAQs
Q1: Python调用C函数时如何处理字符串参数?
A: 对于C风格的字符串(char*),需使用ctypes的c_char_p或CFFI的ffi.new("char[]")进行转换。
# ctypes示例
from ctypes import c_char_p
lib.print_str(c_char_p(b"Hello")) # 注意字节串
# CFFI示例
ffi.cdef("void print_str(char *str);")
lib.print_str(ffi.new("char[]", b"Hello"))Q2: 如何在Python中安全地执行带用户输入的Linux命令?
A: 应避免直接拼接用户输入到命令中,改用参数化方式:
import subprocess
# 危险做法(不推荐)
user_input = "; rm -rf /"
subprocess.run(f"ls {user_input}", shell=True)
# 安全做法(推荐)
user_input = "important_file.txt"
subprocess.run(['ls', '-l', user_input], check=True)通过将用户输入作为独立参数传递,可防止shell注入攻击。
文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/398022.html<
