You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式Python 3.6中禁用内置模块导入的实现方案咨询

禁用Python 3.6中import命令的实现方法

这是嵌入式Python场景里很常见的安全需求,我给你几个经过验证的靠谱方案,你可以根据自己的C++嵌入场景选择合适的组合:

1. 替换内置的__import__函数

Python里的import本质是调用内置的__import__函数,我们可以把它替换成自定义的限制版本,只允许导入你的C++模块:

import builtins

# 先保存原始的__import__函数
original_import = builtins.__import__

def restricted_import(name, *args, **kwargs):
    # 这里列出你允许导入的自定义模块名称
    allowed_modules = {"my_custom_cpp_module"}
    if name not in allowed_modules:
        raise ImportError(f"导入模块 '{name}' 是不被允许的")
    # 允许的模块调用原始导入函数
    return original_import(name, *args, **kwargs)

# 替换内置的__import__
builtins.__import__ = restricted_import

注意点:这个方法简单直接,但如果用户能拿到builtins的引用,理论上可以改回原始函数。所以最好在初始化Python解释器的第一时间就设置这个替换,同时结合其他限制手段。

2. 通过sys.modules占位阻止内置模块导入

我们可以提前把所有内置模块在sys.modules里设为None或者空对象,这样当用户尝试导入时会直接报错:

import sys

# 获取所有Python内置模块的名称
builtin_module_list = sys.builtin_module_names

# 把内置模块都占位成None,阻止导入
for module_name in builtin_module_list:
    sys.modules[module_name] = None

# 保留你需要的自定义模块(如果已经加载)
allowed_modules = {"my_custom_cpp_module"}
for module_name in list(sys.modules.keys()):
    if module_name not in allowed_modules and module_name != "sys":
        del sys.modules[module_name]

注意点:不要删除sys、__main__这类核心模块,否则会导致Python解释器崩溃。另外,用户如果手动修改sys.modules可能绕开限制,所以需要配合解释器的沙箱防护。

3. 在C++嵌入层面设置导入钩子(最推荐)

因为你是用C嵌入Python的,直接在C层面修改导入逻辑会更安全,用户在Python脚本里很难绕开。这里是一个简单的实现示例:

#include <Python.h>
#include <cstring>

// 自定义的限制导入函数
static PyObject* restricted_import(PyObject* self, PyObject* args) {
    const char* module_name;
    if (!PyArg_ParseTuple(args, "s", &module_name)) {
        return NULL;
    }

    // 定义允许导入的自定义模块列表
    const char* allowed_modules[] = {"my_custom_cpp_module", NULL};
    int is_allowed = 0;
    for (int i = 0; allowed_modules[i] != NULL; ++i) {
        if (strcmp(module_name, allowed_modules[i]) == 0) {
            is_allowed = 1;
            break;
        }
    }

    if (!is_allowed) {
        PyErr_SetString(PyExc_ImportError, "Import is not permitted");
        return NULL;
    }

    // 调用原始的__import__函数
    PyObject* builtins = PyEval_GetBuiltins();
    PyObject* original_import = PyDict_GetItemString(builtins, "__import__");
    return PyObject_CallFunctionObjArgs(original_import, PyUnicode_FromString(module_name), NULL);
}

// 定义模块方法
static PyMethodDef RestrictedMethods[] = {
    {"__import__", restricted_import, METH_VARARGS, "Restricted import function"},
    {NULL, NULL, 0, NULL}
};

// 定义限制模块
static struct PyModuleDef RestrictedModule = {
    PyModuleDef_HEAD_INIT,
    "_restricted_import",
    NULL,
    -1,
    RestrictedMethods
};

// 模块初始化函数
PyMODINIT_FUNC PyInit__restricted_import(void) {
    return PyModule_Create(&RestrictedModule);
}

// 在初始化Python解释器后调用这个函数设置限制
void setup_restricted_import() {
    PyObject* builtins = PyEval_GetBuiltins();
    PyObject* restrict_module = PyImport_ImportModule("_restricted_import");
    PyObject* new_import = PyObject_GetAttrString(restrict_module, "__import__");
    PyDict_SetItemString(builtins, "__import__", new_import);
    
    // 释放引用,避免内存泄漏
    Py_DECREF(restrict_module);
    Py_DECREF(new_import);
}

优势:这种底层的钩子完全在C++层面控制,Python脚本无法直接修改,安全性最高,非常适合你的嵌入式场景。

4. 用AST语法树预检查过滤import语句

在执行用户脚本前,我们可以用ast模块解析脚本的语法树,直接拦截所有import和from ... import ...语句:

import ast

class ImportBlocker(ast.NodeTransformer):
    def visit_Import(self, node):
        raise SyntaxError("禁止使用import语句")
    
    def visit_ImportFrom(self, node):
        raise SyntaxError("禁止使用from...import语句")

def validate_script(script_content):
    try:
        tree = ast.parse(script_content)
        transformer = ImportBlocker()
        transformer.visit(tree)
        ast.fix_missing_locations(tree)
        return compile(tree, "<user_script>", "exec")
    except SyntaxError as e:
        raise e

# 使用示例
user_script = """
import os
print(os.getcwd())
"""
try:
    compiled_script = validate_script(user_script)
    exec(compiled_script)
except SyntaxError as e:
    print(f"脚本验证失败: {e}")

注意点:这个方法能提前拦截显式的import语句,但要注意用户可能用exec、eval动态生成import代码,所以需要同时限制这些内置函数的使用。

推荐组合方案

为了达到最好的防护效果,建议你:

  • 优先使用C++层面的导入钩子(最安全)
  • 配合AST语法预检查,提前拦截import语句
  • 再加上sys.modules占位,作为最后一层防护

这样多层限制基本能完全阻止用户导入任何内置模块,只允许使用Python语言本身和你的自定义C++模块。

内容的提问来源于stack exchange,提问作者kovacsv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:25:43