Использование модели Django из хука mercurial python

Я пытаюсь поставить в очередь некоторые запросы на сборку в БД во время перехвата группы изменений. Таблица БД управляется приложением Django. Итак, в хуке я хочу использовать модель Django для отправки запроса на сборку. Однако я не могу правильно настроить параметры для успешного импорта модели.

На основании этого (https://docs.djangoproject.com/en/1.3/ref/django-admin/), все, что мне нужно сделать, это добавить мой сайт django в системный путь и установить файл DJANGO_SETTINGS_MODULE. Сайт django находится в /opt/mysite, поэтому попробуйте это из консоли python:

>>> import sys
>>> import os
>>> sys.path.append('/opt')
>>> os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
>>> from mysite.myapp.models import Build
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/mysite/myapp/models.py", line 1, in <module>
    from django.db import models
  File "/usr/lib/pymodules/python2.7/django/db/__init__.py", line 78, in <module>
    connection = connections[DEFAULT_DB_ALIAS]
  File "/usr/lib/pymodules/python2.7/django/db/utils.py", line 93, in __getitem__
    backend = load_backend(db['ENGINE'])
  File "/usr/lib/pymodules/python2.7/django/db/utils.py", line 33, in load_backend
    return import_module('.base', backend_name)
  File "/usr/lib/pymodules/python2.7/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/usr/lib/pymodules/python2.7/django/db/backends/mysql/base.py", line 28, in <module>
    from django.db import utils
ImportError: cannot import name utils
>>>

Вторая попытка:

На основании этого (http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/) я могу использовать setup_environ(), когда я пробую это в оболочке python, это работает:

>>> import sys
>>> sys.path.append('/opt')
>>> from django.core.management import setup_environ
>>> from mysite import settings
>>> setup_environ(settings)
'/opt/mysite'
>>> from mysite.myapp.models import Build
>>> Build.objects.all()
[<Build: #1 F nkj sdfsdfsdfs43qg test_branch>, <Build: #2 F nkj sdfsdfsdfs43qg test_branch>, <Build: #13 Q   >, <Build: #14 Q   nkj_bug243>, <Build: #11 F nkj 444hwe45hedrrt nkj_bug272>, <Build: #12 F nkj sdfsdfsdfs43qg test_branch>]

Однако, когда я пробую это в своем хуке Mercurial, я получаю ошибки в ту минуту, когда пытаюсь импортировать свою модель сборки:

#!/usr/bin/env python
import sys
path = '/opt'
if path not in sys.path:
    sys.path.append(path)

from django.core.management import setup_environ
from mysite import settings
setup_environ(settings)

from mysite.myapp.models import Build
import datetime

... do stuff ...

Когда он доходит до строки «from mysite.myapp.models import Build», я получаю следующий вывод ошибки:

** unknown exception encountered, please report by visiting
**  http://mercurial.selenic.com/wiki/BugTracker
** Python 2.7.2+ (default, Oct  4 2011, 20:06:09) [GCC 4.6.1]
** Mercurial Distributed SCM (version 1.9.1)
** Extensions loaded:
Traceback (most recent call last):
  File "/usr/bin/hg", line 38, in <module>
    mercurial.dispatch.run()
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 27, in run
    sys.exit(dispatch(request(sys.argv[1:])))
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 64, in dispatch
    return _runcatch(req)
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 87, in _runcatch
    return _dispatch(req)
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 679, in _dispatch
    cmdpats, cmdoptions)
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 454, in runcommand
    ret = _runcommand(ui, options, cmd, d)
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 733, in _runcommand
    return checkargs()
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 687, in checkargs
return cmdfunc()
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 676, in <lambda>
    d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
  File "/usr/lib/python2.7/dist-packages/mercurial/util.py", line 385, in check
return func(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/mercurial/commands.py", line 3884, in push
    newbranch=opts.get('new_branch'))
  File "/usr/lib/python2.7/dist-packages/mercurial/localrepo.py", line 1428, in push
lock=lock)
  File "/usr/lib/python2.7/dist-packages/mercurial/localrepo.py", line 1849, in addchangegroup
source=srctype, url=url)
  File "/usr/lib/python2.7/dist-packages/mercurial/localrepo.py", line 224, in hook
    return hook.hook(self.ui, self, name, throw, **args)
  File "/usr/lib/python2.7/dist-packages/mercurial/hook.py", line 160, in hook
    mod = extensions.loadpath(path, 'hghook.%s' % hname)
  File "/usr/lib/python2.7/dist-packages/mercurial/extensions.py", line 45, in loadpath
    return imp.load_source(module_name, path)
  File "/opt/unapse/belvedere/mercurial_hook.py", line 14, in <module>
    from unapse.belvedere.models import Build
  File "/usr/lib/python2.7/dist-packages/mercurial/demandimport.py", line 109, in _demandimport
    mod = _origimport(name, globals, locals)
  File "/opt/unapse/belvedere/models.py", line 1, in <module>
    from django.db import models
  File "/usr/lib/python2.7/dist-packages/mercurial/demandimport.py", line 109, in _demandimport
    mod = _origimport(name, globals, locals)
  File "/usr/lib/pymodules/python2.7/django/db/__init__.py", line 14, in <module>
    if not settings.DATABASES:
  File "/usr/lib/pymodules/python2.7/django/utils/functional.py", line 276, in __getattr__
    self._setup()
  File "/usr/lib/pymodules/python2.7/django/conf/__init__.py", line 42, in _setup
    self._wrapped = Settings(settings_module)
  File "/usr/lib/pymodules/python2.7/django/conf/__init__.py", line 139, in __init__
    logging_config_func(self.LOGGING)
  File "/usr/lib/python2.7/logging/config.py", line 776, in dictConfig
    dictConfigClass(config).configure()
  File "/usr/lib/python2.7/logging/config.py", line 575, in configure
    '%r: %s' % (name, e))
ValueError: Unable to configure handler 'mail_admins': __import__() argument 1 must be string, not DictConfigurator

Любые идеи относительно того, что может быть причиной этой проблемы?


person Nick Jennings    schedule 08.03.2012    source источник
comment
Прочтите эту статью о запуске автономных скриптов Django... b-list.org/weblog/2007/sep/22/standalone-django-scripts   -  person    schedule 08.03.2012
comment
Это для подсказки, я прочитал статью и попытался реализовать один из методов там. У меня это сработало в консоли Python, но когда я попробовал то же самое в своем ртутном хуке, это не удалось. Я обновил свой пост, указав результат этой попытки.   -  person Nick Jennings    schedule 08.03.2012


Ответы (2)


Ошибка DictConfigurator — это ошибка в python, которая, как мы надеемся, будет исправлена ​​в следующей версии 2.7 (http://bugs.python.org/issue12718), что-то (вероятно, mercurial) переопределяет import, и в этом случае код регистрации Python дает сбой.

А пока вот что я сделал, чтобы исправить это. Скопируйте dictconfig.py из django/utils куда-нибудь по системному пути python (я поместил его рядом с моим хуком). Изменить строку

importer = __import__

to:

def importer(self, *args):
    return __import(*args)__

А затем в settings.py для вашего проекта django добавьте в конец:

LOGGING_CONFIG = 'website.dictconfig.dictConfig'

Обновите веб-сайт.dictconfig до любого пути, по которому вы поместили файл dictconfig, чтобы python мог его найти.

ОБНОВЛЕНИЕ: я думаю, что есть еще более простой способ. Добавьте это в начало вашего хука, прежде чем импортировать что-либо еще:

from mercurial import demandimport;
demandimport.disable()

Это заставляет Mercurial отменить переопределение import и, кажется, чисто решает проблему.

person Dave Townsend    schedule 28.03.2013

Если вы работаете со своей средой в каталоге virtualenv, вам нужно добавить его в пакеты сайта, и я также предлагаю вам поместить каталог django в начало sys.path, а не в конец.

Вот код, который мы используем для интеграции нашего приложения Django в другие приложения Python.

import os
import sys

# point this at the virtualenv dir that your django deployment runs out of
# you are using virtualenv. right?
DJANGO_ENV = '/home/core/python-envs/production'

# where your code lives (ie where settings.py is)
DJANGO_DIR = '/home/core/code/production'

# add our site packages
import site
site_packages = os.path.join(DJANGO_ENV, 'lib', 'python%s' % sys.version[:3], 'site-packages')
site.addsitedir(site_packages)

# put the main Django directory on first
sys.path.insert(0, DJANGO_DIR)

# setup the Django environment pointing to our settings
import settings
import django.core.management
django.core.management.setup_environ(settings)

# finally, import our objects
from yourapp.models import YourModel

Последнее, что следует отметить, это то, что когда мы импортируем наш код в некоторые приложения, мы сталкиваемся с проблемами области видимости и конфликтами импорта. Чтобы обойти это, мы оборачиваем работу, которую хотим выполнить, в функцию, чтобы она получила собственную область видимости.

Например, вместо:

from yourapp.models import YourModel
objs = YourModel.objects.filter(something=True)
...

Сделайте что-нибудь вроде:

def do_work():
    from yourapp.models import YourModel
    objs = YourModel.objects.filter(something=True)
    ...
do_work()
person Evan Borgstrom    schedule 05.04.2012