我试图在我的Python C扩展中调试内存崩溃,并尝试在valgrind下运行脚本.我发现valgrind输出中有太多的"噪音",即使我运行简单的命令:
valgrind python -c ""
Run Code Online (Sandbox Code Playgroud)
Valgrind输出完整的重复信息,如下所示:
==12317== Invalid read of size 4
==12317== at 0x409CF59: PyObject_Free (in /usr/lib/libpython2.5.so.1.0)
==12317== by 0x405C7C7: PyGrammar_RemoveAccelerators (in /usr/lib/libpython2.5.so.1.0)
==12317== by 0x410A1EC: Py_Finalize (in /usr/lib/libpython2.5.so.1.0)
==12317== by 0x4114FD1: Py_Main (in /usr/lib/libpython2.5.so.1.0)
==12317== by 0x8048591: main (in /usr/bin/python2.5)
==12317== Address 0x43CD010 is 7,016 bytes inside a block of size 8,208 free'd
==12317== at 0x4022F6C: free (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==12317== by 0x4107ACC: PyArena_Free (in /usr/lib/libpython2.5.so.1.0)
==12317== by 0x41095D7: PyRun_StringFlags (in /usr/lib/libpython2.5.so.1.0)
==12317== by 0x40DF262: (within /usr/lib/libpython2.5.so.1.0)
==12317== …Run Code Online (Sandbox Code Playgroud) 我一直在努力学习如何为Python编写C扩展,并希望确定我理解PyArg_ParseTupleAndKeywords的工作原理.
我相信第一个参数是一个PyObject指针,它指向一个参数数组,这些参数按照它们传递的顺序传递给C-extension函数.第二个参数是传递的关键字列表,它们被传递的位置,以及非常可能的某种指示标记,告诉关键字开始和位置变得无关紧要.
然后,PyArg_ParseTupleAndKeywords使用其关键字列表(第四个参数)来映射用关键字指定的参数,以及格式字符串(第三个参数)和应该复制适当值的C变量(第五个和+参数)的地址.
我的理解是否正确?当我阅读在线文档时,我所看到的只是对"位置参数和关键字参数"的引用,这让我感到有些不知所措.处理PyArg_ParseTupleAndKeywords的Python解释器的文件在哪里?
我已经创建了一个C扩展,我想在我的Python包中启用(使用setuptools),只有传入命令行选项.最简单的方法是什么?
我似乎无法找到任何直截了当的方式来解决这个问题.
我试图找出在C扩展模块中如何为函数提供一个变量(也许是)相当多的参数.
阅读有关PyArg_ParseTuple的内容,您似乎必须知道要接受多少,一些是必需的,一些是可选的,但都有自己的变量.我希望PyArg_UnpackTuple能够处理这个问题,但是当我尝试以错误的方式使用它时,它似乎只会给我总线错误.
作为一个例子,将以下可能想要的python代码放入扩展模块(在C中).
def hypot(*vals):
if len(vals) !=1 :
return math.sqrt(sum((v ** 2 for v in vals)))
else:
return math.sqrt(sum((v ** 2 for v in vals[0])))
Run Code Online (Sandbox Code Playgroud)
这可以用任何数量的参数调用或遍历,hypot(3,4,5),hypot([3,4,5]),并hypot(*[3,4,5])都给予了同样的答案.
我的C函数的开头看起来像这样
static PyObject *hypot_tb(PyObject *self, PyObject *args) {
// lots of code
// PyArg_ParseTuple or PyArg_UnpackTuple
}
Run Code Online (Sandbox Code Playgroud)
许多人认为是yasar11732.这里的下一个人是一个完全正常工作的扩展模块(_toolboxmodule.c),它只接受任何数字或整数参数,并返回由这些参数组成的列表(名称不好).一个玩具,但说明了需要做什么.
#include <Python.h>
int ParseArguments(long arr[],Py_ssize_t size, PyObject *args) {
/* Get arbitrary number of positive numbers from Py_Tuple */
Py_ssize_t i;
PyObject *temp_p, …Run Code Online (Sandbox Code Playgroud) 如果我理解正确,
PyModule_Create中的PyMODINIT_FUNC 已被Python3.X 取代PyObject*然而,两者都返回Python 3.X,模块的初始化函数必须返回PyObject*模块 - 即
PyMODINIT_FUNC
PyInit_spam(void)
{
return PyModule_Create(&spammodule);
}
Run Code Online (Sandbox Code Playgroud)
而在Python2.X中,这不是必要的 - 即
PyMODINIT_FUNC
initspam(void)
{
(void) Py_InitModule("spam", SpamMethods);
}
Run Code Online (Sandbox Code Playgroud)所以,我的理智检查问题是:
现在,我只是在尝试非常简单的Python C扩展案例.也许如果我做得更多,那么答案就很明显,或者如果我试图将Python嵌入其他东西......
我如何编写一个Cython函数,它将一个字节串对象(一个普通字符串,一个bytearray或另一个跟在缓冲区协议下的对象)作为一个类型化的内存视图?
根据Unicode和Passing Strings Cython教程页面,以下内容应该有效:
cpdef object printbuf(unsigned char[:] buf):
chars = [chr(x) for x in buf]
print repr(''.join(chars))
Run Code Online (Sandbox Code Playgroud)
它适用于bytearrays和其他可写缓冲区:
$ python -c 'import test; test.printbuf(bytearray("test\0ing"))'
'test\x00ing'
Run Code Online (Sandbox Code Playgroud)
但它不适用于普通字符串和其他只读缓冲区对象:
$ python -c 'import test; test.printbuf("test\0ing")'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "test.pyx", line 1, in test.printbuf (test.c:1417)
File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6795)
File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3341)
BufferError: Object is not writable.
Run Code Online (Sandbox Code Playgroud)
查看生成的C代码,Cython总是将PyBUF_WRITABLE标志传递给PyObject_GetBuffer(),这解释了异常. …
我正在尝试调试Python 2.7的C扩展.我使用python2.7调试版本.我建立我的项目,setuptools我setup.py有这样的台词:
ext_modules=[Extension("my.extension",
["my/_extension.c"])]
Run Code Online (Sandbox Code Playgroud)
当我python setup.py install因某种原因调用扩展时编译为带_d后缀的文件,之后,在Python中,我不能这样做import my.extension,我只能这样做import my.extension_d.而我得到的是:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "build/bdist.linux-x86_64/egg/my/extension_d.py", line 7, in <module>
File "build/bdist.linux-x86_64/egg/my/extension_d.py", line 6, in __bootstrap__
ImportError: dynamic module does not define init function (initextension_d)
Run Code Online (Sandbox Code Playgroud)
当然我的扩展没有initextension_d,它只有initextension功能.
这非常不方便,因为我必须更改一些代码并将此_d后缀添加到导入和其他内容中.
是否可以关闭此后缀的前置?或者如何以其他方式处理该问题?也许有一些"官方"的方式?
我使用的是Ubuntu Linux.
我有Python扩展的源代码.我想在调试时查看该扩展的调试符号.如何告诉PIP编译和链接我的扩展的调试符号?
(最好是平台不可知,否则Linux)
上传我的Python C扩展的二进制发行版后python setup.py bdist upload,easy_install [my-package-name]失败"错误:无法在/ tmp/easy_install/package-name-etc-etc中找到安装脚本".
我究竟做错了什么?
我正在为我的Python程序编写一个C扩展用于速度目的,并且遇到一些非常奇怪的行为,试图传入一个三维的numpy数组.它适用于一个二维数组,但我确定我正在搞砸一些指针试图让它与第三维一起工作.但这是奇怪的部分.如果我只是传入一个三维数组,它会因总线错误而崩溃.如果(在Python中)我首先将我的变量创建为2D数组,然后用3D数组覆盖它,它可以完美地工作.如果变量首先是空数组,然后是3D数组,则会发生Seg Fault故障.怎么可能发生这种情况?
此外,任何人都可以帮助我获得3D阵列吗?或者我应该放弃并传递2D数组并自行重塑它?
这是我的C代码:
static PyObject* func(PyObject* self, PyObject* args) {
PyObject *list2_obj;
PyObject *list3_obj;
if (!PyArg_ParseTuple(args, "OO", &list2_obj, &list3_obj))
return NULL;
double **list2;
double ***list3;
//Create C arrays from numpy objects:
int typenum = NPY_DOUBLE;
PyArray_Descr *descr;
descr = PyArray_DescrFromType(typenum);
npy_intp dims[3];
if (PyArray_AsCArray(&list2_obj, (void **)&list2, dims, 2, descr) < 0 || PyArray_AsCArray(&list3_obj, (void ***)&list3, dims, 3, descr) < 0) {
PyErr_SetString(PyExc_TypeError, "error converting to c array");
return NULL;
}
printf("2D: %f, 3D: …Run Code Online (Sandbox Code Playgroud) python ×9
c ×2
cython ×2
python-c-api ×2
binary ×1
debugging ×1
easy-install ×1
memory-leaks ×1
memoryview ×1
numpy ×1
pointers ×1
python-2.7 ×1
python-3.x ×1
setuptools ×1
valgrind ×1