Python: Как я могу переопределить один модуль в пакете с измененной версией, которая живет вне пакета?

Я хотел бы обновить один модуль в пакете Python с моей собственной версией модуля со следующими условиями:

  • Я хочу, чтобы мой обновленный модуль жил за пределами исходного пакета (или потому что у меня нет доступа к источнику пакета, или потому что я хочу удержать свои локальные модификации отдельный repo, и т.д.).
  • Я хочу import операторы, которые относятся к исходному пакету/модулю для разрешения к моему локальному модулю

Вот пример того, что я хотел бы сделать специфические особенности использования от django, потому что это - то, где эта проблема возникла для меня:

Скажите, что это - моя структура проекта

django/
  ... the original, unadulterated django package ...
local_django/
  conf/
    settings.py
myproject/
  __init__.py
  myapp/
    myfile.py

И затем в myfile.py

# These imports should fetch modules from the original django package
from django import models
from django.core.urlresolvers import reverse

# I would like this following import statement to grab a custom version of settings 
# that I define in local_django/conf/settings.py 
from django.conf import settings

def foo():
  return settings.some_setting

Я могу сделать некоторое волшебство с __import__ оператор в myproject/__init__.py выполнять это? Существует ли больше "pythonic" способа достигнуть этого?

Обновление - Почему я хочу сделать это

Вот сценарий, где я думаю, что это имеет смысл.

  • Я запускаюсь, django привел в действие веб-сайт на сервере, который имеет django, предварительно установленный глобально. Я не могу изменить фактический django источник в этом случае.
  • Мой django проект использует третью сторону допускающие повторное использование приложения, и я не хочу изменяться imports во всех тех приложениях для импорта, например mycustomsettings. Я хочу оставить допускающие повторное использование приложения блаженно неосведомленными, что я изменил реализацию django.conf.settings.
13
задан zlovelady 22 May 2010 в 05:39
поделиться

4 ответа

Просто установите запись в sys.modules, прежде чем что-либо еще будет ее импортировать:

import sys
import myreplacement
sys.modules["original"] = myreplacement

Затем, когда кто-то «импортирует оригинал», он получит вместо этого вашу версию.

Если вы хотите заменить подмодуль, вы можете сделать это следующим образом:

import sys
import thepackage
sys.modules["thepackage"].submodule = myreplacement
sys.modules["thepackage.submodule"] = myreplacement

Тогда «from thepackage import submodule» или «import thepackage.submodule» даст «myreplacement».

15
ответ дан 1 December 2019 в 23:47
поделиться

Возможно, вы можете использовать проект django-values ​​, который предоставляет приложение dbsettings , которое ...

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

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

ПРИМЕЧАНИЕ. Это не замена settings.py. Это разработан для ожидаемых значений меняться в зависимости от потребностей сайта или его пользователей, чтобы такие изменения не требуют рестарт. settings.py по-прежнему место для настроек, которые будут зависит только от проекта.

Один из способов взглянуть на это: settings.py предназначен для тех вещей, которые требуются от технического перспектива (соединения с базой данных, установленные приложения, доступные промежуточное ПО и т. д.), а dbsettings - лучше всего для тех вещей, которые требуется в соответствии с политикой организации (квоты, минимальные требования и т. д.). Таким образом, программисты поддерживают технические требования, а администраторы поддерживают организационные политика.

Проект разработан Марти Алчином (написавшим книгу Pro Django) и не требует каких-либо изменений в коде Django - это стандартное приложение Django.

1
ответ дан 1 December 2019 в 23:47
поделиться
import local_django.conf
import django.conf
django.conf.settings = local_django.conf.settings

Модули являются одиночными. Модули инициализируются / загружаются только один раз. Это необходимо сделать перед импортом модулей, использующих django.conf.settings, чтобы они могли принять изменение.

Прочтите эту ссылку для получения дополнительной информации, чтобы узнать, существует ли более стандартный подход к django, поскольку в документации специально не рекомендуется делать это так, как я показываю выше для объекта настроек. http://docs.djangoproject.com/en/dev/topics/settings/ Он должен нормально работать с другими объектами и модулями.

1
ответ дан 1 December 2019 в 23:47
поделиться

В этом конкретном случае «лучше всего было бы следовать предписанному механизму для создания собственных настроек .

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

0
ответ дан 1 December 2019 в 23:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: