Ложные ImportErrors (с модулями, импортирующими подмодули?) - PullRequest
10 голосов
/ 31 августа 2011

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

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)

(и опять то же самое с 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 et al. не удастся. Кажется, что Python как-то забыл о __init__.py и его пространстве имен.

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

Все эти приложения работают на сервере wsgi-to-fastcgi.

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

Любые и все указатели и идеи приветствуются!

Ответы [ 3 ]

1 голос
/ 09 мая 2012

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

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

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

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

Обновление

Для 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, и вы получите сбой и аналогичные выходные данные, запустите python ok.py и все работает.

0 голосов
/ 23 мая 2012

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

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

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

0 голосов
/ 09 мая 2012

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

DIR/django/contrib/gis/...

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

...