虚假导入错误(模块导入子模块?)

发布于 2024-12-02 14:29:23 字数 2033 浏览 1 评论 0原文

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

TLDR: Django 应用程序崩溃,重新启动后它可以运行,但无法导入某些模块。再次重新启动后,一切又恢复正常。

整个故事:

不同的 Python(2.5.x、2.6.x 和 2.6.x)和 Django 版本(分别为 1.1.0、1.2.5 和 1.3.0)上的不同应用程序(目前最多三个)偶尔会出现虚假的导入错误。例如,其中一个应用程序开始通过在内部抛出 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 及其命名空间。

这些应用程序的流量相对较高,可以想象(尽管不确定)它们可能已经超出了虚拟机限制并且几乎可以正常恢复。另外,至少在两种情况下,应用程序之前存在导致崩溃的问题——一种情况是 SIGSEGV,另一种情况是错误……其他情况)。单个应用程序重新启动会导致其引发 ImportErrors,而另一个应用程序重新启动则使其再次正常运行。 .py[c] 已损坏?时间戳是古老的。

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

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

任何和所有的指示和想法表示赞赏!

I have a problem that I don't really know where to begin solving. Maybe it'll ring someone's bell.

TLDR: a Django app crashes and upon restart it runs but fails to import some modules. Upon another restart, all is fine again.

The whole story:

Different applications (we're up to three right now) on different Python (2.5.x, 2.6.x and 2.6.x) and Django versions (1.1.0, 1.2.5 and 1.3.0, respectively) occasionally exhibit spurious ImportErrors. For example, one of these apps started to fail every request by throwing an ImportError inside:

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

We collected strace output and the relevant chunk is below (absolute path replaced with DIR for brevity and protecting the guilty).

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)

(and once again the same thing s/GMarker/GEvent/)

After restarting the process everything runs smoothly, also running:

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

produces no errors.

The GMarker and GEvent classes are actually defined in django.contrib.gis.maps.google.overlays and imported in ...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

so it's fully expected that loading GMarker.py et al. will fail. It seems that Python has somehow forgotten about __init__.py and its namespace.

The apps are relatively high-traffic and it is conceivable (though not certain) that they might have exceeded their VM limits and recovered almost-gracefully. Also, at least in two cases the app had earlier problems leading to a crash -- SIGSEGV in one case, and err... something else in the other). A single app restart caused it to throw ImportErrors around, and another one made it behave again. Corrupted .py[c]? Timestamps are ancient.

All these apps are running on flup the wsgi-to-fastcgi server.

Each of these apps failed once so far (in completely different modules, two cases of __init__.py "forgotten" but I cannot find the third error ATM) so I cannot tell whether the modules are somehow meaningful.

Any and all pointers and ideas appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苯莒 2024-12-09 14:29:23

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

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

  1. 有人修改了 sys.path 并且该路径不再位于模块路径内
  2. 这些模块中的循环导入,这是由您首先从另一个模块导入触发的!
  3. 您有站点冲突(是的,有这种情况),从不同站点包位置加载相同的模块,
  4. 您在搜索路径中有一个模块与某处的其他模块或系统模块发生冲突。

如果您粘贴第二组 strace 行,我们会更接近解决方案吗?

更新

2。我的意思是,如果您有 2 个具有以下结构的文件

foo.py/init.py:

from bar import baz

bar.py/init.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 一切正常。

Actually your strace line does not help a bit; those accesses did not result in the module being imported.

There might be multiple reasons for such import errors:

  1. someone modifies sys.path and that is not within the module path anymore
  2. a cyclical import in those modules, that is triggered by you importing from another module first!
  3. you have site conflict (yep, had that kind of), same module being loaded from different site packages locations
  4. you have a module in the search path conflicting with an other module somewhere, or with a system module.

If you would paste the SECOND set of strace lines, we would be closer to solution?

Update

For 2. I mean that if you have 2 files with the following structure

foo.py/init.py:

from bar import baz

bar.py/init.py:

import foo
def baz():
     pass

snafu.py:

import bar
import foo

ok.py:

import foo
import snafu

Run python snafu.py and you get a crash and similar strace output, run python ok.py and everything works.

梦幻的味道 2024-12-09 14:29:23

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

DIR/django/contrib/gis/...

我想知道这个 DIR 部分。您是否可能在某处错误输入了 PYTHONPATH 变量,使用了 DIR 而不是 $DIR?

The strace output seems suspicious to me:

DIR/django/contrib/gis/...

I am wondering about this DIR part. Is it possible you misstyped the PYTHONPATH variable somewhere, using DIRinstead of $DIR?

要走干脆点 2024-12-09 14:29:23

我建议您使用 try... except ImportError 包装导入,并添加执行类似操作的代码(任何记录而不是打印的内容都可以)

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

这应该让您了解发生了什么。

I'd suggest you to wrap the import with a try... except ImportError and add a code doing something like that (anything that logs, instead of print, will do)

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

This should let you understand what's happening.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文