在共享包结构的一部分的不同目录中创建多个Python模块

时间:2009-08-06 00:41:28

标签: python django

我正在开发一个包含单个应用程序的Django项目。该应用程序将在GPL下发布,因此我想与项目分开开发 - 使用该应用程序的个人网站。我试图在项目和应用程序中使用基于我的域名的包结构,这就是我遇到问题的地方。

这是我的文件结构(适当时带有__init__.py文件):

$HOME/django-sites/mydomain
$HOME/django-apps/mydomain/cms

我的PYTHONPATH:

$HOME/django-sites:$HOME/django-apps

如果我启动Python解释器(来自文件系统上的任何目录),我可以从站点导入类,但不能导入应用程序。如果我颠倒了PYTHONPATH中的两个条目(首先是应用程序,然后是网站)的顺序,我可以从应用程序而不是网站导入。

看起来Python只是试图从包含包名的第一部分的PYTHONPATH中的第一个条目导入。那是对的吗?这是预期的行为吗?如果是这样,我只能在域/ app1,domain / app2这样的包结构中粘贴模块,如果它们位于相同的目录结构中 - 无论PYTHONPATH如何。

它不是show-stopper,因为我可以重命名该网站,但它与我期待的大不相同。 Python教程提到__path__,但我不知道如何使用它:

  

Packages支持另一个特殊属性__path__。这被初始化为一个列表,其中包含在执行该文件中的代码之前保存包的__init__.py的目录的名称。这个变量可以修改;这样做会影响将来对包中包含的模块和子包的搜索。

     

虽然通常不需要此功能,但它可用于扩展程序包中的模块集。

还有其他人遇到过这个吗?我可以用__path__做一些事情来使这个功能按预期进行吗?

3 个答案:

答案 0 :(得分:4)

以下是程序包__path____init__.py的使用方式:

$ export PYTHONPATH=$HOME/django-sites
$ ls -d $HOME/django*
django-apps/  django-sites/ 
$ cat /tmp/django-sites/mydomain/__init__.py
import os

_components = __path__[0].split(os.path.sep)
if _components[-2] == 'django-sites':
  _components[-2] = 'django-apps'
  __path__.append(os.path.sep.join(_components))

$ python -c'import mydomain; import mydomain.foo'
foo here /tmp/django-apps/mydomain/foo.pyc
$ 

如您所见,这会使django-apps/mydomain包的一部分内容mydomain__init__.py位于django-sites/mydomain下) - 您不需要{{为了这个目的,在django-apps上也可以使用此方法。

这是否比@ defrex的回答更好的安排可能没有实际意义,但是因为一个软件包丰富了它的sys.path是一个非常重要的python程序员的工具包,我想我有更好的说明无论如何; - )。

答案 1 :(得分:1)

您的分析似乎是正确的。 python路径用于定位要导入的模块; python导入它找到的第一个。我不知道你可以做些什么来解决这个问题,除了将模块命名为不同的东西或将它们放在搜索路径中的相同位置。

答案 2 :(得分:1)

你基本上有两个名为相同的模块(mydomain)。为什么不这样设置你的PYTHONPATH?

$HOME/django-sites:$HOME/django-apps/mydomain

这可以避免导入问题。