我可以从它的内存地址中获取一个 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)",而不是&lt;tuple at 0x10ed51908&gt;。此外,即使对于没有有用表示的对象,返回 &lt;TYPE at ADDR&gt; 只是许多类型遵循的未说明约定(也是用户定义类的默认值),不是您可以依赖的。

不过,既然你大概只关心 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 对象吗?的主要内容,如果未能解决你的问题,请参考以下文章

从它的元类python引用一个类的实例

Python 7 多线程及进程

2/20Python之四则运算

python的变量与数据类型

Python当中的array数组对象

Python小数据池(转)