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

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

  • Я хочу, чтобы мой обновленный модуль жил за пределами исходного пакета (либо потому, что у меня нет доступа к источнику пакета, либо потому, что я хочу сохранить свои локальные модификации в отдельном репозитории и т. Д.).
  • Я хочу 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, чтобы выполнить это? Есть ли более «питонный» способ добиться этого?

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

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

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

Ответы [ 5 ]

14 голосов
/ 22 мая 2010

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

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

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

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

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

Тогда «из подмодуля импорта пакета» или «импортировать модуль упаковки» выдаст «myreplacement».

1 голос
/ 22 мая 2010

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

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

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

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

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

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

1 голос
/ 22 мая 2010
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/ Он должен хорошо работать для других объектов и модулей.

0 голосов
/ 16 января 2013

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

Подробнее о virtualenv можно узнать из Информация virtualenv .

Существует также пакет "virtualenvwrapper", который предоставляет инструменты для более простого переключения между средами.

По общему признанию, у меня нет большого опыта с этим, и я нашел этот вопрос в попытке понять, как переопределить Стандартную Библиотеку Python с помощью пользовательской версии - так что это не идеально. Но я, тем не менее, впечатлен его способностью указать, что вы устанавливаете, вплоть до версии отдельного модуля!

0 голосов
/ 22 мая 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...