【问题标题】:What could cause a python module to be imported twice?什么可能导致 python 模块被导入两次?
【发布时间】:2011-01-25 20:42:11
【问题描述】:

据我了解,python 模块永远不会导入两次,即模块中的代码只会在第一次导入时执行。后续的导入语句只是将模块添加到导入的范围内。

我有一个名为“TiledConvC3D.py”的模块,但它似乎被多次导入。我使用 pdb 在此模块的代码顶部打印堆栈。

这是第一次执行模块时堆栈跟踪的结尾:

File "<anonymized>/python_modules/Theano/theano/gof/cmodule.py", line 328, in refresh
  key = cPickle.load(open(key_pkl, 'rb'))
File "<anonymized>/ops/TiledConvG3D.py", line 565, in <module>
  import TiledConvC3D
File "<anonymized>/ops/TiledConvC3D.py", line 18, in <module>
  pdb.traceback.print_stack()

它会继续执行几次。但是,第二次调用的完整堆栈跟踪未显示对 reload 的任何调用,因此不应发生这些执行:

File "sup_train_conj_grad.py", line 103, in <module>
  dataset = Config.get_dataset(dataset_node)
File "<anonymized>/Config.py", line 279, in get_dataset
  from datasets import NewWiskott
File "<anonymized>/datasets/NewWiskott.py", line 16, in <module>
  normalizer_train = video.ContrastNormalizer3D(sigma, global_per_frame = False, input_is_5d = True)
File "<anonymized>/util/video.py", line 204, in __init__
  self.f = theano.function([input],output)
File "<anonymized>/python_modules/Theano/theano/compile/function.py", line 105, in function
  allow_input_downcast=allow_input_downcast)
File "<anonymized>/python_modules/Theano/theano/compile/pfunc.py", line 270, in pfunc
  accept_inplace=accept_inplace, name=name)
File "<anonymized>/python_modules/Theano/theano/compile/function_module.py", line 1105, in orig_function
  fn = Maker(inputs, outputs, mode, accept_inplace = accept_inplace).create(defaults)
File "/u/goodfeli/python_modules/Theano/theano/compile/function_module.py", line 982, in create
  _fn, _i, _o = self.linker.make_thunk(input_storage = input_storage_lists)
File "<anonymized>/python_modules/Theano/theano/gof/link.py", line 321, in make_thunk
  output_storage = output_storage)[:3]
File "<anonymized>/python_modules/Theano/theano/gof/cc.py", line 1178, in make_all
  output_storage = node_output_storage)
File "<anonymized>/python_modules/Theano/theano/gof/cc.py", line 774, in make_thunk
  cthunk, in_storage, out_storage, error_storage = self.__compile__(input_storage, output_storage)
File "<anonymized>/python_modules/Theano/theano/gof/cc.py", line 723, in __compile__
  output_storage)
File "<anonymized>/python_modules/Theano/theano/gof/cc.py", line 1037, in cthunk_factory
  module = get_module_cache().module_from_key(key=key, fn=self.compile_cmodule)
File "<anonymized>/python_modules/Theano/theano/gof/cc.py", line 59, in get_module_cache
  return cmodule.get_module_cache(config.compiledir)
File "<anonymized>/python_modules/Theano/theano/gof/cmodule.py", line 576, in get_module_cache
  _module_cache = ModuleCache(dirname, force_fresh=force_fresh)
File "<anonymized>/python_modules/Theano/theano/gof/cmodule.py", line 268, in __init__
  self.refresh()
File "<anonymized>/python_modules/Theano/theano/gof/cmodule.py", line 326, in refresh
  key = cPickle.load(open(key_pkl, 'rb'))
File "<anonymized>/ops/TiledConvV3D.py", line 504, in <module>
  import TiledConvG3D
File "<anonymized>/ops/TiledConvG3D.py", line 565, in <module>
  import TiledConvC3D
File "<anonymized>/ops/TiledConvC3D.py", line 22, in <module>
  pdb.traceback.print_stack()

此外,我还检查了 __builtin__.__import__ 的 id。在我的主脚本的最开始,我导入__builtin__ 并打印id(__builtin__.__import__),然后再进行任何其他导入。我还从我的模块内部打印了id(__builtin__.import__),该模块被多次导入,并且 id 的值没有改变。

除了调用 reload 和覆盖 __builtin__.__import__ 之外,还有其他机制可以解释我的模块被多次加载吗?

【问题讨论】:

    标签: python module import


    【解决方案1】:

    如果在路径中找到两次 Python 模块,则可以导入两次。例如,假设您的项目布局如下:

    • 源/
      • 包1/
        • spam.py
        • eggs.py

    假设您的 PYTHONPATH (sys.path) 包含 src 和 src/package1:

    PYTHONPATH=/path/to/src:/path/to/src/package1
    

    如果是这种情况,您可以像这样导入同一个模块两次:

    from package1 import spam
    import spam
    

    而 Python 会认为它们是不同的模块。这是怎么回事?

    此外,根据下面的讨论(对于搜索此问题的用户),可以两次导入模块的另一种方法是,如果在第一次导入中途出现异常。例如,如果垃圾邮件导入鸡蛋,但导入鸡蛋导致模块内部出现异常,则可以再次导入。

    【讨论】:

    • 这是一个很好的观点,但我不认为在这种情况下会发生这种情况。正如您在堆栈跟踪中看到的那样,在两种情况下都使用相同的语句导入模块:“import TiledConvC3D”
    • 第一次导入中途是否有可能失败?例如,如果在导入模块的过程中出现异常?
    • 是的,这就是问题所在。我没有意识到在 try 语句中允许导入。
    • 我被双路径问题击中并来到这里 - 谢谢你在这里!
    • 在您的示例中,对于每种导入垃圾邮件的方式,sys.modules 中的键是什么?你能链接到一些文档(比如python-notes.curiousefficiency.org/en/latest/python_concepts/…)吗?
    猜你喜欢
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2012-03-07
    相关资源
    最近更新 更多