Ошибочные импортные ошибки (с модулями, импортирующими подмодули?)

У меня есть проблема, что я не знаю, с чего начать решение. Может быть, кто-то позвонит.

TL;DR: приложение 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 и его пространстве имен.

Приложения имеют относительно высокий трафик, и возможно (хотя и не обязательно), что они, возможно, превысили свои пределы VM и восстановились почти изящно. Кроме того, по крайней мере, в двух случаях у приложения были более ранние проблемы, приводящие к сбою - SIGSEGV в одном случае, и ошибка... что-то другое в другом). Один перезапуск приложения заставлял его бросать ImportErrors, а другой заставлял его снова вести себя. Повреждено .py [c]? Временные метки древние.

Все эти приложения запущены на сервере wsgi-to-fastcgi.

Каждое из этих приложений провалилось один раз (в совершенно разных модулях, два случая __init__.py "забыты", но я не могу найти третий банкомат ошибок), поэтому я не могу сказать, насколько модули имеют какое-то значение.

Любые и все указатели и идеи оценены!

Ответ 1

На самом деле ваша линия strace немного не помогает; эти обращения не привели к вводу импортируемого модуля.

Для таких ошибок импорта может быть несколько причин:

  • кто-то изменяет sys.path и больше не находится в пути к модулю
  • циклический импорт в эти модули, который запускается при первом входе с другого модуля!
  • у вас есть конфликт сайта (да, у него такой), тот же модуль загружается из разных мест размещения сайтов.
  • У вас есть модуль в пути поиска, конфликтующий с другим модулем где-то или с системным модулем.

Если вы вставляете ВТОРОЙ набор линий strace, мы будем ближе к решению?

Update

Для 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 и все будет работать.

Ответ 2

Выход strace кажется мне подозрительным:

DIR/django/contrib/gis/...

Мне интересно об этой части DIR. Возможно, вы где-то ошибочно указали переменную PYTHONPATH, используя DIR вместо $DIR?

Ответ 3

Я бы предложил вам обернуть импорт с помощью try... за исключением ImportError и добавить код, делающий что-то вроде этого (что-нибудь, что будет делать журналы, а не печать)

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

Это позволит вам понять, что происходит.