- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直无法让 Python C API 给我错误。
背景: 我一直在使用 ctypes
运行 native 代码 (C++) 一段时间,但直到现在我还没有真正用 Python C 做过任何具体的事情应用程序接口(interface)。我主要只是从 Python 传入结构并从 C++ 填充它们。我使用结构的方式变得很麻烦,所以我决定尝试直接在 C++ 中创建 Python 对象,然后将它们传回我的 Python 脚本。
代码:我有一个只有一个功能的 DLL (Foo.dll
):
#define N 223
__declspec(dllexport) void Bar(void)
{
std::cout << "Bar" << std::endl;
for (int i = 0; i < N; ++i)
{
auto list = PyList_New(0);
std::cout << "Created: " << i << std::endl;
//Py_DECREF(list);
}
}
然后我有正在运行的 Python 脚本:
import ctypes as C
dll = r"C:\path\to\dll\Foo.dll"
Foo = C.CDLL(dll)
# lists = [[] for _ in range(0)]
Foo.Bar()
print "Done."
会发生什么:如果我在上面的 DLL 中将 N
定义为 222
或以下,代码可以正常工作(除了内存泄漏,但这不是问题)。
如果我取消注释 //Py_DECREF(list)
行,代码可以正常工作。
但是,通过上面的代码,我得到了这个:
Bar
Created: 0
Created: 1
Created: 2
...(omitted for your sake)
Created: 219
Created: 220
Created: 221
Traceback (most recent call last):
File "C:\path_to_script\script.py", line 9, in <module>
Foo.Bar()
WindowsError: exception: access violation reading 0x00000028
事实上,我用字典、列表、元组等得到了同样的结果。如果我创建一个列表然后将空子列表附加到该列表,我会得到相同的结果。
更奇怪的是,我在实际 Python 脚本中制作的每个列表都会减少 DLL 在出现此 Windows 错误之前可以制作的列表数量。
更奇怪的是,如果我在我的 python 脚本中创建超过 222 个列表,那么 DLL 将不会遇到此错误,直到它创建了 720 个更多 列表。
**其他细节:**
Python.h
和 python27.lib
2.7.13::Anaconda 自定义(32 位)
只要我不从我的 C++ 代码中创建很多 PyObject
,一切似乎都运行良好。我可以将 PyObject
传入和传出 Python 代码,它工作正常......直到我从我的 C++ 代码中创建了“太多”的对象。
这是怎么回事?
最佳答案
From the documentation for CDLL :
The Python global interpreter lock is released before calling any function exported by these libraries, and reacquired afterwards.
这使得使用 Python C API 代码不安全。正如您所发现的,它究竟是如何失败的是不可预测的。我猜这与分配是否触发垃圾收集器运行有关,但我认为不值得花太多时间来找出确切原因。
有(至少)两种解决方案可供选择:
ctypes.PyDLL
(文档注释类似于CDLL
,只是它不释放GIL)在您的 C++ 代码中重新获取 GIL - 一种简单的方法是:
auto state = PyGILState_Ensure();
// C++ code requiring GIL - probably your entire loop
PyGILState_Release(state);
关于Python C API : WindowsError after creating some number of PyObjects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47310250/
我是初学者。在这里学习。 一段代码抛出 WindowsError。我捕捉到它并将其重命名为 exception。 我通过dir(exception)、type(exception)、print(exc
我已经创建了一个临时文件。 向创建的文件添加了一些数据。 保存了它,然后试图删除它。 但我遇到了 WindowsError。编辑后我关闭了文件。如何检查哪个其他进程正在访问该文件。 C:\Docume
我正在学习 Python(使用 Python 3.2)并且一直在遵循一些手册。其中之一,我被要求将当前目录更改为包含我被要求制作并放置在那里的特定文件的目录。我一直遇到以下错误: >>> import
Python 内置了通用 OSError 的异常。 , 它有 WindowsError它继承自 OSError。文档解释说 WindowsError 是 Raised when a Windows-s
使用Python的rename()函数重命名文件时出现问题,提示 WindowsError: [Error 2] 错误,最初代码如下: ?
这个简短的函数只是获取存储设备的可用空间,但是在运行代码时出现上述错误。 功能是: def disk_space1(drive): freespace = ctypes.c_ulonglong
这是我的问题的一个简化示例: import os import sqlite3 with sqlite3.connect('test.db.temp') as db: db.executesc
关于 Windows 上 Python 的快速问题。我有一个编译程序的脚本(使用安装规则),然后通过网络将构建产品移动到远程目标。 但是,我不断收到 WindowsError 5 Access Den
我正在尝试了解 Windows 8 上 Python 2.7.6 的异常。 这是我正在测试的代码,旨在在 My_New_Dir 中创建一个新目录。如果目录已经存在,我想删除整个目录及其内容,然后创建一
我在使用Scrapy的FifoDiskQueue时遇到了这个问题。在 Windows 中,FifoDiskQueue 将导致目录和文件由一个文件描述符创建并由另一个文件描述符使用(如果队列中没有更多消
我正在使用 killableprocess 包(建立在子进程之上)来运行进程每当我在脚本中运行“killableprocess.Popen(command)”这段代码时,我都会收到以下错误: File
我正在尝试在 QGIS 上开发 python 插件,并且我正在尝试使用子进程执行二进制程序: program = os.path.join(self.tranusConf.tranusBinPath,
setup.py from distutils.core import setup import py2exe setup(console=['program.py']) 错误 Traceback (
在我的程序中,我有一个函数 runScript(): def runScript(): subprocess.call(['echo', 'hello']) 我在 Python 文档中看到过许多类似的
在 Windows 上,当我尝试创建以下文件夹时: os.mkdir('H:\\__ Photos\\____Photos to be sorted\\[ Photo sorting proc
我正在尝试使用 Python 的 ctypes 来处理 DLL,但是当我尝试调用作为指向另一个函数的指针传递的函数时,我偶尔会遇到问题。 一点背景...我正在尝试使用 Dokan 构建用户空间文件系统
我正在尝试使用 Py2exe 构建我的独立可执行文件。我导入了 Pmw 类。当我运行 stanalone 可执行文件时,出现此错误: Traceback (most recent call last)
我在绘制 VBO 时遇到 PyOpenGL 函数 glDrawArrays() 问题。我有一个对象(类)ContactGeometry,我使用方法 create_VBO() 创建 VBO 并使用方法
我一直无法让 Python C API 给我错误。 背景: 我一直在使用 ctypes 运行 native 代码 (C++) 一段时间,但直到现在我还没有真正用 Python C 做过任何具体的事情应
运行 Windows 7 和 Python 2.7.8,使用 RotatingFileHandler 进行日志记录,并使用 subprocess.Popen 使得 RotatingFileHandle
我是一名优秀的程序员,十分优秀!