python运行时错误:在迭代期间字典更改了大小,在scipy导入期间随机弹出

2024-03-29 00:38:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用torch和kalman filter,我正在用importlib以一种非标准的方式导入它,大致如下所示:

import importlib


class Foo():
    def __init__(self):
        pass

    def tst(self):
        torch = importlib.import_module("torch")
        kalman = importlib.import_module("filterpy.kalman")


foo = Foo()
foo.tst()

我的程序没有生成任何线程(至少我自己没有生成任何线程,我检查了threading.enumerate()的输出,它只包含MainThread

我面临以下问题:

在导入过程中,我时不时地(大约10%的尝试中)观察到RuntimeError抛出的scipy

  File "/opt/my_package/imp.py", line 492, in import_class
    imported_module = importlib.import_module("filterpy.kalman")
  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/opt/venv/lib/python3.8/site-packages/filterpy/kalman/__init__.py", line 22, in <module>
    from .EKF import *
  File "/opt/venv/lib/python3.8/site-packages/filterpy/kalman/EKF.py", line 28, in <module>
    from filterpy.stats import logpdf
  File "/opt/venv/lib/python3.8/site-packages/filterpy/stats/__init__.py", line 22, in <module>
    from .stats import *
  File "/opt/venv/lib/python3.8/site-packages/filterpy/stats/stats.py", line 32, in <module>
    from scipy.stats import norm, multivariate_normal
  File "/opt/venv/lib/python3.8/site-packages/scipy/stats/__init__.py", line 391, in <module>
    from .stats import *
  File "/opt/venv/lib/python3.8/site-packages/scipy/stats/stats.py", line 180, in <module>
    from . import distributions
  File "/opt/venv/lib/python3.8/site-packages/scipy/stats/distributions.py", line 12, in <module>
    from . import _discrete_distns
  File "/opt/venv/lib/python3.8/site-packages/scipy/stats/_discrete_distns.py", line 1266, in <module>
    pairs = list(globals().items())

有趣的是,当我在一台机器(AWS G4实例)上运行我的停靠代码时,却在另一台具有相同停靠映像的机器上看不到它时,我出现了这个错误。我看到,在发生此问题的机器上,如果我在启动后直接调用它,则更可能遇到此问题,机器启动的时间越长,问题出现的可能性就越小

我在scipy存储库中发现了这个关闭的问题:https://github.com/scipy/scipy/issues/11479-但问题似乎没有被识别出来(至少我看不到问题的正确解释)

这里还有另外一个问题,但除了关于呼叫list():Bug in Python 3.5? list(globals().items()) caused RuntimeError: dictionary changed size during iteration的有用评论之外,没有得到任何答案

还有这样一个问题:Python: globals().items() iterations try to change a dict-但是scipy不会在循环中迭代globals().items(),而是使用列表理解。此外,这个问题不容易重现——它并不是每次都表现出来,根据我的观察,它是随机表现出来的。基于这个问题,在调用pairs = list(globals().items())之前添加pairs = []可以解决问题,即使是这样,我们也应该在每次运行时看到这个问题

我确实明白,如果我的程序是多线程程序,那么list(globals().items())可能就是这种情况。但是我只有MainThread,怎么可能globals().items()在迭代时发生变化呢

即使我运行的是单线程代码,我也尝试过这样包装我的代码(如这里所建议的:Forcing a thread to block all other threads from executing),但运气不好:

original_interval = sys.getswitchinterval()
sys.setswitchinterval(1000)
# imports
sys.setswitchinterval(original_interval)

我还研究了pairs = list(globals().items())的反汇编,但由于我没有阅读反汇编代码的经验,所以我看不到任何问题:

import dis
dis.dis("pairs = list(globals().items())")

  1           0 LOAD_NAME                0 (list)
              2 LOAD_NAME                1 (globals)
              4 CALL_FUNCTION            0
              6 LOAD_METHOD              2 (items)
              8 CALL_METHOD              0
             10 CALL_FUNCTION            1
             12 STORE_NAME               3 (pairs)
             14 LOAD_CONST               0 (None)
             16 RETURN_VALUE

我正在nvidia/cuda:11.0-cudnn8-devel-ubuntu18.04容器中运行python 3.8.0。Scipy版本:1.6.3。我不确定这是否有什么关系,但我还有numpy 1.20.3torch 1.7.1+cu110


Tags: inpyimportvenvlibstatslinesite