我可以从它的内存地址中获取一个 python 对象吗?
Posted
技术标签:
【中文标题】我可以从它的内存地址中获取一个 python 对象吗?【英文标题】:Can I get a python object from its memory address? 【发布时间】:2013-03-22 20:30:06 【问题描述】:我正在学习如何将 Qt 与 PyQt 一起使用,并且我有一个带有 StandardItemModel 的 QTabelView 我已成功填充模型并将 itemChanged 信号连接到插槽。我想弄乱 IPython 中返回的任何对象,所以目前我有这行:
def itemChangedSlot(epw, item):
new_data = item.data()
print new_data
print item
打印出来的
<PyQt4.QtGui.QStandardItem object at 0x07C5F930>
<PyQt4.QtCore.QVariant object at 0x07D331F0>
在 IPython 会话中是否可以使用此内存地址获取对象?我在 Google 上没有看到任何内容,也许我的术语不对?
【问题讨论】:
您正在打印的对象new_data
就是对象。只需退回或以其他方式存储,而不是打印它。
这不是不可能做到的,但这并不容易,而且没有记录在任何情况下都可以工作,而且这通常是一个非常糟糕的主意。如果您正在试验 CPython 如何在幕后工作,或者调试垃圾收集器,或者类似的东西,那么这可能是值得的,但否则,您就找错了树,而 Raymond Hettinger 的答案就是您想要的.
是的,尝试在地址后使用 .__dict__
【参考方案1】:
您需要持有对对象的引用(即将其分配给变量或将其存储在列表中)。
没有语言支持直接从对象地址到对象(即pointer dereferencing)。
【讨论】:
【参考方案2】:您几乎肯定问错了问题,而 Raymond Hettinger 的答案几乎肯定是您真正想要的。
这样的东西可能有助于深入研究 CPython 解释器的内部结构以用于学习目的或审计它的安全漏洞或其他什么……但即便如此,您最好还是将 Python 解释器嵌入到程序中并编写将你想要的任何东西暴露给 Python 解释器的函数,或者至少编写一个 C 扩展模块来让你操作 CPython 对象。
但是,如果你真的需要这样做……
首先,没有可靠的方法可以从repr
获取地址。大多数具有有用eval
-able 表示的对象都会给你。比如('1', 1)
的repr是"('1', 1)"
,而不是<tuple at 0x10ed51908>
。此外,即使对于没有有用表示的对象,返回 <TYPE at ADDR>
只是许多类型遵循的未说明约定(也是用户定义类的默认值),不是您可以依赖的。
不过,既然你大概只关心 CPython,你可以依赖id
:
CPython 实现细节:这是对象在内存中的地址。
(当然,如果你有对象可以调用id
(或repr
),你不需要通过指针取消引用它,如果你没有对象,它可能已经被垃圾回收了所以没有什么可以取消引用的,但也许你还有它,只是不记得你把它放在哪里了……)
接下来,你如何处理这个地址?好吧,Python 没有公开任何与id
相反的函数。但是Python C API 是有据可查的——而且,如果您的 Python 是围绕共享库构建的,则可以通过 ctypes
访问该 C API,只需加载它即可。事实上,ctypes
提供了一个特殊变量,可以自动加载正确的共享库以调用 C API,ctypes.pythonapi
。
在非常旧的ctypes
版本中,您可能必须显式查找并加载它,例如pydll = ctypes.cdll.LoadLibrary('/usr/lib/libpython2.5.so')
(这是针对安装在/usr/lib 中的Python 2.5 的Linux;显然,如果这些细节中的任何一个不同,则确切的命令行会有所不同。)
当然,这样做比做任何有用的事情更容易使 Python 解释器崩溃,但做任何有用的事情并非不可能,您可能会喜欢尝试它。
【讨论】:
以上是关于我可以从它的内存地址中获取一个 python 对象吗?的主要内容,如果未能解决你的问题,请参考以下文章