- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
作为将我的游戏引擎代码转换为 cython 的一部分,我正在移植我的顶点缓冲区对象 (Vbo) 类。我使用这个 Vbo 类将 3D 模型数据发送到 GPU。代码 (vbo.pyx
) 当前如下所示:
cimport gl
from enum import Enum
import contextlib
class VboTarget(Enum):
ARRAY = gl.GL_ARRAY_BUFFER
INDEX = gl.GL_ELEMENT_ARRAY_BUFFER
cdef class Vbo:
cdef readonly gl.GLuint id_
cdef readonly double[:] data
cdef readonly int target
def __init__(self, data=None, target=VboTarget.ARRAY):
gl.glewInit()
gl.glGenBuffers(1, &self.id_)
self.target = target.value
if data is not None:
self.data = data
@contextlib.contextmanager
def bind(self):
gl.glBindBuffer(self.target, self.id_)
try:
yield
finally:
gl.glBindBuffer(self.target, 0)
def set_data(self, new_data):
self.data = new_data
def update(self):#perform gpu update
with self.bind():
gl.glBufferData(self.target, self.data.nbytes, &self.data[0], gl.GL_DYNAMIC_DRAW)
我想使用 contextlib
,因为它可以确保缓冲区绑定(bind)和解除绑定(bind)到 GPU 的操作干净且自动进行。 cython代码编译无误;然而,当我将这个 cython 模块导入到我的 python 代码中时,我收到以下错误消息:
Traceback (most recent call last):
File "main.py", line 2, in <module>
import vbo
File "vbo.pyx", line 21, in init vbo (vbo.c:15766)
@contextlib.contextmanager
File "C:\Python27\lib\contextlib.py", line 82, in contextmanager
@wraps(func)
File "C:\Python27\lib\functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'method_descriptor' object has no attribute '__module__'
我不太确定如何解释这条消息。我可以将 contextlib
装饰器与 cdef class
一起使用吗?如果可以,如何使用? contextlib
是否与 cython 兼容?
更新:这是使用 __enter__
和 __exit__
的替代版本:
cimport gl
from enum import Enum
from cpython cimport array
import array
class VboTarget(Enum):
ARRAY = gl.GL_ARRAY_BUFFER
INDEX = gl.GL_ELEMENT_ARRAY_BUFFER
cdef class Vbo:
cdef readonly gl.GLuint id_
cdef readonly float[:] data
cdef readonly int target
def __init__(self, data=None, target=VboTarget.ARRAY):
gl.glewInit()
gl.glGenBuffers(1, &self.id_)
self.target = target.value
if data is not None:
self.data = data
def set_data(self, float[:] new_data):
self.data = new_data
def update(self):#perform gpu update
with self:
gl.glBufferData(self.target, self.data.nbytes, &self.data[0], gl.GL_STATIC_DRAW)
def __enter__(self):
gl.glBindBuffer(self.target, self.id_)
def __exit__(self, exc_type, exc_val, exc_tb):
gl.glBindBuffer(self.target, 0)
最佳答案
尝试了您的代码的简化版本后,它似乎对我有用(Cython 0.25.1,Python 3.6.1):
import contextlib
cdef class Vbo:
def __init__(self):
pass
@contextlib.contextmanager
def bind(self):
self.do_something()
try:
yield
finally:
print("Finally")
def do_something(self):
print("something")
我不认为你更复杂的例子的任何变化实际上应该影响这个,但我没有 gl.pxd
所以很难测试。可能值得确保您的 Cython 版本是最新的(如果您还没有)...
编辑:我认为重要的区别可能是 Python 2.7 与 Python 3.6。 Python 3.6 has an AttributeError
catch block而 Python 2.7 doesn't catch the error .因此,我认为这不是 Cython 行为的变化,因此可能不是真正的错误。
正如评论中所讨论的,您可以使用非cdef
class
和 __enter__
和 __exit__
来得到相同的行为:
cdef class Vbo:
def __init__(self):
pass
def bind(self):
class C:
def __enter__(self2):
# note that I can access "self" from the enclosing function
# provided I rename the parameter passed to __enter__
self.do_something() # gl.BindBuffer(self.target, self.id_) for you
def __exit__(self2, exc_type, exc_val, exc_tb):
print("Done") # gl.glBindBuffer(self.target, 0)
return C()
def do_something(self):
print("something")
总而言之 - 我无法重现您的问题,但这里有一个替代方案...
关于python - 将 contextlib 与 cython 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44733520/
自从我知道了这个模式,我就一直在使用 with open('myfile.txt','w') as myfile: with contextlib.redirect_stdout(myfile
我在 Ubuntu 上使用 Python3.5。以下脚本创建一个文件 out 并用越来越多的“Hello”行填充它: import contextlib with contextlib.redirec
我正在尝试创建一个包装器来使上下文对象成为可选的。当条件为真时,事物应该表现得像包装的上下文对象,否则它应该表现得像无操作上下文对象。此示例适用于使用一次包装对象,但失败了,它被重新使用。 例子: i
我明白了why contextlib.nested is deprecated . 但是如果我为旧的 python 版本编写程序而没有 with 的多种形式(即 < 2.7),我(几乎)别无选择。 为
有谁知道我在哪里可以找到这个 python 模块“contextlib”? root@overo:~# python
我们的代码根据运行时参数调用可变数量的上下文管理器: from contextlib import nested, contextmanager @contextmanager def my_cont
为什么我可以跳过在 yield log_func 中调用 log_func,即我可以只写 yield 而代码仍然有效。这是为什么? yield 在这种情况下如何工作? import time from
假设我有一个上下文管理器: @contextmanager def cm(x): y = f(x) z = yield y g(z) 如何将 z 发送到上下文管理器? 我试过:
我使用 Python2.7 并且我想要函数:contextlib.redirect_stdout . 我的意思是,我想重定向特定函数的输出(不是所有程序)。 问题是 - 只有 Python3 支持“c
作为将我的游戏引擎代码转换为 cython 的一部分,我正在移植我的顶点缓冲区对象 (Vbo) 类。我使用这个 Vbo 类将 3D 模型数据发送到 GPU。代码 (vbo.pyx) 当前如下所示: c
我在 python 中使用 with 语句( PEP 343 ) 时遇到了一些问题,以便在上下文之后自动管理资源清理。特别是,with 语句 始终假定资源清理方法是 .close()。 IE。在下面的
为了以编程方式组合上下文管理器,我使用以下代码: == helpers.py == from contextlib import nested import mock def multiple_pat
context.nested 已被弃用,我试图理解这背后的基本原理,在阅读了很长时间的文档后,我看不到一个例子来说明第二个问题: Secondly, if the __enter__() method
我真的很喜欢“with open('in_file'') as f”这个语法。我想将该语法用于必须打开和关闭的我自己的资源。 但是,我不明白如何更改我的 open() 方法以启用“with”语法。我可
from contextlib import closing def init_db(): with closing(connect_db()) as db: with app
尝试从 docker 运行命令时,我遇到了这个错误 google 计算引擎上的 docker 容器。 这是堆栈跟踪: Traceback (most recent call last): File
为了以编程方式组合上下文管理器,我使用以下代码: == helpers.py == from contextlib import nested import mock def multiple_pat
为了说明我的问题,这里有一个不使用 contextlib 的基本请求: import urllib.request url = "http://www.example.com/"
在寻找性能错误的过程中,我终于确定问题的根源是 contextlib 包装器。开销相当惊人,我没想到这是减速的根源。减速在 50 倍的范围内,我无法承受循环。如果它有可能显着减慢速度,我肯定会感谢文档
为什么要使用 contextlib.suppress 来抑制异常,而不是使用 try/except 和 pass? 这两种方法在字符数量上没有区别(如果有的话,suppress 有更多的字符),即使代
我是一名优秀的程序员,十分优秀!