Spurious ImportErrors(模块导入子模块?)

时间:2011-08-31 17:30:23

标签: python django import importerror

我有一个问题,我真的不知道从哪里开始解决。也许它会敲响别人的钟声。

TLDR: Django应用程序崩溃,重启后运行但无法导入某些模块。再次重启时,一切都很好。

整个故事:

偶尔在不同的Python(2.5.x,2.6.x和2.6.x)和Django版本(分别为1.1.0,1.2.5和1.3.0)上的不同应用程序(我们现在最多三个)展示虚假的ImportErrors。例如,其中一个应用程序通过在其中抛出ImportError开始使每个请求失败:

from django.contrib.gis.maps.google import GMarker, GEvent

我们收集了strace输出,相关的块在下面(为了简洁和保护有罪,绝对路径被DIR取代)。

stat64("DIR/django/contrib/gis/maps/google/GMarker", 0xf699ce3c) = -1 ENOENT (No such file or directory)
open("DIR/django/contrib/gis/maps/google/GMarker.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("DIR/django/contrib/gis/maps/google/GMarkermodule.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("DIR/django/contrib/gis/maps/google/GMarker.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("DIR/django/contrib/gis/maps/google/GMarker.pyc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)

(再一次是同样的事情s / GMarker / GEvent /)

重新启动流程后,一切运行顺利,同时运行:

python -c 'from django.contrib.gis.maps.google import GMarker'

不会产生错误。

GMarker和GEvent类实际上是在django.contrib.gis.maps.google.overlays中定义的,并在...maps/google/__init__.py中导入:

from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet
from django.contrib.gis.maps.google.overlays import GEvent, GIcon, GMarker, GPolygon, GPolyline
from django.contrib.gis.maps.google.zoom import GoogleZoom

因此完全可以预期加载GMarker.py等。将失败。似乎Python已经忘记了__init__.py及其命名空间。

这些应用程序的流量相对较高,可以想象(虽然不确定)它们可能已经超出了VM的限制并且几乎可以优雅地恢复。此外,至少在两种情况下,应用程序早先出现导致崩溃的问题 - 一种情况下出现SIGSEGV,另一种出现错误......其他情况。单个应用程序重新启动导致它抛出ImportErrors,另一个使它再次运行。瑕疵.py [c]?时间戳很古老。

所有这些应用程序都在wsgi-to-fastcgi服务器上运行。

到目前为止,这些应用程序中的每一个都失败了一次(在完全不同的模块中,有两个__init__.py被遗忘的情况“但是我找不到第三个错误的ATM)所以我无法判断模块是否在某种程度上有意义。

赞赏所有指针和想法!

3 个答案:

答案 0 :(得分:1)

实际上你的strace线没有帮助;这些访问不会导致模块被导入。

此类导入错误可能有多种原因:

  1. 有人修改了sys.path并且不再在模块路径中
  2. 在这些模块中循环导入,这是由您首先从另一个模块导入的!
  3. 你有站点冲突(是的,有那种),从不同的站点包位置加载相同的模块
  4. 您的搜索路径中的某个模块与其他模块或某个系统模块冲突。
  5. 如果要粘贴第二组strace线,我们会更接近解决方案吗?

    更新

    对于2.我的意思是如果你有2个具有以下结构的文件

    foo.py/的初始化的.py:

    from bar import baz
    

    bar.py/的初始化的.py:

    import foo
    def baz():
         pass
    

    snafu.py:

    import bar
    import foo
    

    ok.py:

    import foo
    import snafu
    

    运行python snafu.py并且你得到一个崩溃和类似的strace输出,运行python ok.py并且一切正常。

答案 1 :(得分:0)

strace输出对我来说似乎很可疑:

DIR/django/contrib/gis/...

我想知道这个DIR部分。是否有可能使用DIR代替$DIR在某处错误地输入了PYTHONPATH变量?

答案 2 :(得分:0)

我建议你用try尝试包装导入...除了ImportError并添加代码做类似的事情(任何记录,而不是打印,都会这样做)

import sys
print sys.modules["django.contrib.gis.maps.google"]
print dir(sys.modules["django.contrib.gis.maps.google"])

这可以让你了解正在发生的事情。