什么原因会导致一个 Python 模块被导入两次?

7 浏览
0 Comments

什么原因会导致一个 Python 模块被导入两次?

据我所知,Python模块不会被重复导入,即模块中的代码只在第一次导入时执行。后续的导入语句只是将该模块添加到导入的范围中。

然而,我有一个名为"TiledConvC3D.py"的模块似乎被多次导入。我使用pdb在该模块的代码顶部打印堆栈。

以下是模块第一次执行时堆栈跟踪的末尾:

File "/python_modules/Theano/theano/gof/cmodule.py",第328行,在refresh函数中
  key = cPickle.load(open(key_pkl, 'rb'))
File "/ops/TiledConvG3D.py",第565行,在中
  import TiledConvC3D
File "/ops/TiledConvC3D.py",第18行,在中
  pdb.traceback.print_stack()

它继续执行几次。然而,第二次调用它时的完整堆栈跟踪没有显示任何调用reload,所以这些执行不应该发生:

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

此外,我还检查了__builtin__.__import__的id。在我的主脚本的开头,我导入__builtin__并打印id(__builtin__.__import__),然后再进行其他导入。我还从我的被多次导入的模块中打印id(__builtin__.import__),而id的值没有发生变化。

除了调用reload和重写__builtin__.__import__,还有其他机制可以解释我的模块为什么会被多次加载吗?

0
0 Comments

在我的情况下,当我在调试模式下运行Flask时,它可能会加载模块不止两次,而是多次。这种情况发生在我身上,我就是无法理解,直到我找到了这个问题。以下是更多信息:

在上述链接中,有人遇到了类似的问题,他们发现问题是由于Flask的调试模式导致的。在调试模式下,Flask会自动监测代码的更改并重新加载模块。这意味着每次更改代码后,Flask都会重新加载模块,从而导致模块被导入多次的问题。

解决这个问题的方法是禁用Flask的调试模式。可以通过在运行Flask应用程序时将调试模式设置为False来实现。这样一来,Flask将不会自动重新加载模块,解决了模块被导入多次的问题。

以下是禁用Flask调试模式的示例代码:

app = Flask(__name__)
app.debug = False

在上面的代码中,我们将Flask应用程序的调试模式设置为False,从而禁用了调试模式。这样一来,即使我们在运行应用程序时进行了代码更改,Flask也不会重新加载模块,避免了模块被导入多次的问题。

希望这些信息能够帮助到其他人解决类似的问题。如果你还有其他问题,可以在上面提供的链接中找到更多有关Flask调试模式的讨论。

0
0 Comments

出现这种情况的原因是当Python模块在路径中被找到了两次时,它会被导入两次。如果项目的布局如上所示,那么就会出现这种情况。假设PYTHONPATH(sys.path)包括src和src/package1。在这种情况下,可以像下面这样导入相同的模块两次,Python会认为它们是不同的模块:

from package1 import spam

import spam

还有一种情况是,如果在第一次导入过程中出现异常,模块也可能被导入两次。例如,如果spam导入eggs,但是导入eggs时发生了异常,那么模块可以再次被导入。

这个问题的解决方法是,在导入模块时避免重复导入。可以使用try语句来包裹导入语句,以捕获导入过程中的异常,并处理异常情况。

出现这个问题后,如果有人决定再次导入模块,模块级变量将会再次被初始化,这样使用起来就非常不安全了。这对于装饰器来说尤其重要,因为它们在导入过程中的多个点上运行。

关于每种导入spam的方式在sys.modules中的键是什么,可以参考一些文档(比如python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html#the-double-import-trap)。

0