Python:如何使用包含在包外的修改版本覆盖包中的一个模块?

时间:2010-05-22 05:19:59

标签: python django

我想用我自己的模块版本更新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语句来完成此操作吗?是否有更“pythonic”的方法来实现这一目标?

更新 - 我为什么要这样做

这是我认为这是有道理的情景。

  • 我正在全球预装django的服务器上启动django支持的网站。在这种情况下,我无法修改实际的django源。
  • 我的django项目使用第三方可重复使用的应用程序,我不想在所有要导入的应用程序中更改imports,例如mycustomsettings。我想让可重用的应用程序幸福地无知我已经改变了django.conf.settings的实现。

5 个答案:

答案 0 :(得分:14)

只需在其他任何内容导入之前在sys.modules中设置该条目:

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

然后,当有人“导入原创”时,他们会获得你的版本。

如果要替换子模块,可以这样做:

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

然后“从包装导入子模块”或“导入thepackage.submodule”将给出“myreplacement”。

答案 1 :(得分:1)

也许您可以使用django-values项目,该项目提供dbsettings应用,其中......

  

...允许占位符进行设置   在Python中定义,而他们的值   由工作人员使用编辑设置   服务器已启动并正在运行。许多   值类型可用,它们   每个映射到本机Python类型,所以   模型方法和其他Python代码   可以作为标准类访问它们   属性。

     

还做了很多努力   减少此功能的开销,   这样只查询数据库   每次服务器重启期间一次,和   仅在值时更新   他们自己更新。

     

注意:这不是作为一个   替换settings.py。这是   专为预期的价值而设计   根据需要改变   网站或其用户,这样的   变化不需要那么多   重新开始。 settings.py仍然是   放置设置的地方   仅因项目而异。

     

一种看待它的方法是   settings.py适用于那些事情   是技术要求   透视(数据库连接,   已安装的应用程序,avaialble   中间件等),而dbsettings是   最适合那些事情   由于组织政策的要求   (配额,最低要求等)。   这样,程序员就可以维持   技术要求,而   管理员维护组织   政策。

该项目由Marty Alchin编写(编写Pro Django书籍)并且不需要对Django代码进行任何更改 - 它是标准的Django应用程序。

答案 2 :(得分:1)

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/ 它应该适用于其他对象和模块。

答案 3 :(得分:0)

在这种特殊情况下,'最好遵循规定的mechanism for creating your own settings

在一般情况下,使用进口产品可能会让您的读者感到困惑(可能是您)。改变类行为的pythonic方法是子类和覆盖。

答案 4 :(得分:0)

我在大约两三天前被介绍过,但是这样做的一种方法是使用Python虚拟环境。这允许您指定您正在使用的Python版本,以及您要安装的模块的版本,并且能够相对容易地在不同版本和项目之间进行交换;它还允许您安装Python系统,否则您可能无法获得安装所需的权限。

您可以从virtualenv info了解有关virtualenv的更多信息。

还有一个“virtualenvwrapper”软件包,它提供了更容易在环境之间交换的工具。

不可否认,我对此没有多少经验,我发现这个问题试图了解如何使用自定义版本覆盖Python标准库 - 所以它并不完美。但是,我对其安装指定的能力印象深刻,直到单个模块的版本!