【问题标题】:Changed address of value on second import第二次导入时更改了值的地址
【发布时间】:2019-01-13 19:25:27
【问题描述】:

我很难理解为什么当我导入一个定义变量的模块并从一个模块访问它时,它有一个地址,而当稍后在另一个模块中导入定义模块时,它又有另一个地址。

测试用例:

#definer.py
value = 0

#firstModule.py
import definer
print(id(definer.value))  # outputs i.e. 1453872004

#otherModule.py
import definer
print(id(definer.value))  # outputs 1453872212

难道不应该是一样的,因为在otherModule.py 中它正在导入缓存的definer.py,因此它应该访问已经创建的对象还是我错过了导入点? otherModule 是创建本地副本还是确实在创造新价值?

【问题讨论】:

  • 你是从同一个进程调用这些方法吗?
  • 我无法复制;只要将firstModuleotherModule 都导入到同一个Python 进程中,definer.value 就会匹配。您的示例代码似乎不是minimal reproducible example,因为您没有显示如何导入firstModule/otherModule;如果您在单独的进程中执行此操作,则预计会出现不匹配。
  • @ShadowRanger 两个导入都是在主进程中进行的。不幸的是,是的,我没有指定某些工作是在另一个进程中完成的,但据我所知,线程线程具有共享内存。
  • @ntrme:这些ids 是printed 在同一个过程中吗?在 CPython 参考解释器中,0 是一个单例(实现细节),所以即使你做了一些奇怪的事情导致 value 在两个地方重新定义,id 也会匹配 unless您涉及到单独的进程(即便如此,我认为只有在 Windows 上使用 subprocessmultiprocessing 时才会发生这种情况,其中工作人员是通过 spawn 而不是 fork 制作的)。或者,您的任何代码是否分配给definer.value?如果是这样,id 将在分配后更改。
  • @ShadowRanger 是的,有分配,但稍后在代码中,在打印语句之后。打印语句是从一个线程(主)发出的,对此进行了仔细检查。因此,我重新安排了代码,从现在开始,我不再只访问值并使用它,而是创建一个对象,在其中设置和获取该值。现在它按预期工作,这意味着我使用一个对象(在某个地址),后来所有线程也都在使用这个对象。我将尝试在简单的设置中复制初始问题并尽快更新问题。无论如何,谢谢你。

标签: python python-2.7 python-import memory-address python-module


【解决方案1】:
 enable_generated_tests_p  cat firstModule.py
import definer
import os

print('pid:',os.getpid(), 'definer.value:',id(definer.value))

 enable_generated_tests_p  cat secondModule.py
import definer
import os

print('pid:',os.getpid(), 'definer.value:',id(definer.value))

 enable_generated_tests_p  cat ThirdModule.py
import firstModule
import secondModule

 enable_generated_tests_p  python firstModule.py
pid: 73848 definer.value: 4565266656

 enable_generated_tests_p  python secondModule.py
pid: 73906 definer.value: 4428878048

 enable_generated_tests_p  python ThirdModule.py
pid: 73964 definer.value: 4442521824
pid: 73964 definer.value: 4442521824

id() - 返回一个对象的“身份”。这是一个整数,保证在其生命周期内对于该对象是唯一且恒定的。具有不重叠生命周期的两个对象可能具有相同的 id() 值。

在您的情况下,您一直在使用不同的进程/子进程运行 firstModule 和 secondModule,因此您获得了不同的 ID,如上所示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-22
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多