Python C扩展导入程序如何使用导入锁定

时间:2019-01-27 13:07:40

标签: python python-c-api python-3.7

背景

我正在构建importer来加密我的代码。编译时,我会加密pyc文件中的代码对象。加载时,我使用此自定义的导入程序在执行之前解密代码对象。

由于我的代码是以zip格式捆绑在一起的,所以我决定通过向其内置的zipimport包中添加解密逻辑来修改zipimporter

我正在使用Python 3.7

问题

我修改了zimpimport.c并将其变成C扩展名。加密和解密过程运行良好,但我开始看到ImportErrorAttributeError。例如:

"""module: test.py"""
class Foo:

    def bar():
        pass

foo = Foo()

// Import Error: can not import name 'foo' from test 
// Attribute Error: foo has no attribute bar

服务器启动时,仅在前几分钟内随机发生此错误。因此,我怀疑这是一个多线程问题,并且是由线程看到部分初始化的模块对象引起的。

我尝试过的事情

检查原始c代码后,加载模块的实现是:

mod = PyImport_AddModuleObject(fullname);
// ... some code
mod = PyImport_ExecCodeModuleObject(fullname, code, modpath, NULL);

首先将模块添加到sys.modules,然后执行一些C代码并最终执行模块代码。如果另一个线程在完成执行模块代码之前读取了sys.modules,则可以获取ImportErrorAttributeError

我只是复制原始实现,并且不使用导入锁。我想它是由外层的解释器处理的,我必须显式地使用导入锁。因此,我用导入锁包装了代码块,如下所示:

#include "import.h"
_PyImport_AcquireLock();
// wrapped code block
_PyImport_ReleaseLock();

我的问题

添加导入锁后,错误仍然发生。我对python c api不熟悉。我是否以正确的方式使用了锁?还有其他可能导致此错误的原因吗?

代码

要进行测试,请将以下文件放在同一文件夹中:

运行python setup.py build_ext --inplace,它将生成zzimporter.so。它的工作方式类似于buit-in zipimport模块。

0 个答案:

没有答案