Python C 扩展导致 stat ENOENT

Python C extension causes stat ENOENT

我正在尝试在 Python 中实现 C 扩展。扩展有效,但一旦导入模块,errno 就会设置为 ENOENT (2)。

simple.c

#include <Python.h>
#include <errno.h>

static PyMethodDef KeypadMethods[] = {
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

PyMODINIT_FUNC initkeypadinterface(void)
{
    PyObject* m;
    int stat;

    stat = errno;
    if (stat)
    {
        printf("There was an error: %d\n", stat);
    }

    m = Py_InitModule3("keypadinterface", KeypadMethods, "Interface to the keypad driver");
    if (m == NULL)
    {
        return;
    }
}

setup.py

from distutils.core import setup, Extension

module1 = Extension('keypadinterface',
                    sources = ['simple.c'])

setup (name = 'KeypadInterface',
       version = '0.1',
       description = 'Provides a python interface to the keypad driver',
       ext_modules = [module1])

python setup.py build 输出:

running build
running build_ext
building 'keypadinterface' extension
creating build
creating build/temp.linux-x86_64-2.7
x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c simple.c -o build/temp.linux-x86_64-2.7/simple.o
creating build/lib.linux-x86_64-2.7
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security build/temp.linux-x86_64-2.7/simple.o -o build/lib.linux-x86_64-2.7/keypadinterface.so

在 errno 上使用带有监视的 gdb 会导致此回溯:

(gdb) c
Continuing.
Hardware watchpoint 1: errno

Old value = 0
New value = 2
0x00007f9974e271d0 in __xstat64 () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007f9974e271d0 in __xstat64 () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00000000004d4ea6 in stat (__path=<optimized out>, __statbuf=<optimized out>)
    at /usr/include/x86_64-linux-gnu/sys/stat.h:455
#2  isdir (path=0x14bf430 "keypadinterface") at ../Python/import.c:133
#3  find_module.38998 (fullname=fullname@entry=0x14be420 "keypadinterface", subname=<optimized out>, 
    subname@entry=0x14be420 "keypadinterface", 
    path=['', '/usr/local/lib/python2.7/dist-packages/esptool-0.1.0-py2.7.egg', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client'], path@entry=0x0, buf=<optimized out>, buf@entry=0x14bf430 "keypadinterface", 
    buflen=buflen@entry=4097, p_fp=p_fp@entry=0x7fff1d45bb80, p_loader=p_loader@entry=0x7fff1d45bb70)
    at ../Python/import.c:1497
#4  0x0000000000540922 in import_submodule.39248 (mod=mod@entry=None, 
    subname=subname@entry=0x14be420 "keypadinterface", fullname=0x14be420 "keypadinterface")
    at ../Python/import.c:2689
#5  0x0000000000540d08 in load_next (mod=None, altmod=None, p_name=p_name@entry=0x7fff1d45bc78, 
    buf=buf@entry=0x14be420 "keypadinterface", p_buflen=p_buflen@entry=0x7fff1d45bc80)
    at ../Python/import.c:2515
#6  0x000000000054111b in import_module_level.isra.3.39267 (name=0x0, 
    name@entry=0x7f99753d4d74 "keypadinterface", 
    globals=globals@entry={'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, fromlist=fromlist@entry=None, level=level@entry=-1) at ../Python/import.c:2224
#7  0x000000000051dc50 in PyImport_ImportModuleLevel (level=-1, fromlist=None, locals=<optimized out>, 
    globals={'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, name=0x7f99753d4d74 "keypadinterface") at ../Python/import.c:2288
#8  builtin___import__ (self=<optimized out>, args=<optimized out>, kwds=<optimized out>)
    at ../Python/bltinmodule.c:49
#9  0x00000000004dc9cb in PyObject_Call (kw=0x0, 
    arg=('keypadinterface', {'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, {...}, None), func=<built-in function __import__>)
    at ../Objects/abstract.c:2529
#10 PyEval_CallObjectWithKeywords (func=func@entry=<built-in function __import__>, 
    arg=arg@entry=('keypadinterface', {'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, {...}, None), kw=kw@entry=0x0) at ../Python/ceval.c:3889
#11 0x000000000049b87e in PyEval_EvalFrameEx (
    f=f@entry=Frame 0x7f9975504c20, for file <stdin>, line 1, in <module> (), throwflag=throwflag@entry=0)
    at ../Python/ceval.c:2333
#12 0x00000000004a1634 in PyEval_EvalCodeEx (closure=0x0, defcount=0, defs=0x0, kwcount=0, kws=0x0, 
    argcount=0, args=0x0, locals=<optimized out>, globals=<optimized out>, co=0x7f9975415b30)
    at ../Python/ceval.c:3252
#13 PyEval_EvalCode (locals=<optimized out>, globals=<optimized out>, co=0x7f9975415b30)
    at ../Python/ceval.c:667
#14 run_mod.42576 (mod=mod@entry=0x14bc470, filename=filename@entry=0x60e5bd "<stdin>", 
    globals=<optimized out>, locals=<optimized out>, flags=flags@entry=0x7fff1d45c0b0, 
    arena=arena@entry=0x1444780) at ../Python/pythonrun.c:1370
#15 0x000000000044e87c in PyRun_InteractiveOneFlags (fp=fp@entry=0x7f99750fb640 <_IO_2_1_stdin_>, 
    filename=filename@entry=0x60e5bd "<stdin>", flags=flags@entry=0x7fff1d45c0b0) at ../Python/pythonrun.c:857
#16 0x000000000044e998 in PyRun_InteractiveLoopFlags (fp=fp@entry=0x7f99750fb640 <_IO_2_1_stdin_>, 
    filename=filename@entry=0x60e5bd "<stdin>", flags=flags@entry=0x7fff1d45c0b0) at ../Python/pythonrun.c:777
#17 0x000000000044ed70 in PyRun_AnyFileExFlags (fp=fp@entry=0x7f99750fb640 <_IO_2_1_stdin_>, 
    filename=filename@entry=0x60e5bd "<stdin>", closeit=closeit@entry=0, flags=flags@entry=0x7fff1d45c0b0)
    at ../Python/pythonrun.c:746
---Type <return> to continue, or q <return> to quit---
#18 0x000000000044f904 in Py_Main (argc=<optimized out>, argv=0x7fff1d45c268) at ../Modules/main.c:640
#19 0x00007f9974d5dec5 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#20 0x0000000000578c4e in _start ()
(gdb)

我读到统计函数可以将 errno 设置为 ENOENT 当被 stat 编辑的路径组件不存在时。但是模块还能用所以路径一定是正确的吧?

一定是我做了什么蠢到家的事,但我还没找到。

以防万一:Python 2.7.6 on Linux Mint 17.1 with GCC 4.8.4

lot 的代码集 errno 在执行操作之前先发制人,因为多个代码路径可能会导致返回相同的错误。因此,errno 中的值应 忽略 除非代码 显式 returns 错误结果。