从子包访问共享模块

时间:2012-07-16 18:16:59

标签: python code-design package-structuring

我在项目中使用内部导入时遇到了困难。这是我项目的部分树结构:

app
  |- Gui.py
  |- Main.py
  |- logger.py
  |- config.py
  |- WebParser (package)
        |- __init__.py
        |- LinksGrabber.py
        |- LyricsGrabber.py
        |- ImagesGrabber.py
  |- (Many other packages...)

每个软件包的模块都需要logger.pyconfig.py个模块,并且这些模块是独立的(仅使用bulit-in模块)。从内部包中访问这些模块很棘手。

这就是我尝试实现它的方法,用于在WebParser\LinksGrabber.py中启用配置访问和日志记录功能:

# WebParser\__init__.py:
sys.path.append('..') # for outside-package modules
import config
from logger import log

# WebParser\LinksGrabber.py:
import WebParser
config = WebParser.config
log = WebParser.log

问题:

  • 这有代码味道。我敢打赌,有一种更好的方法可以实现这种行为。
  • 我想立即致电import WebParser并使用WebParser.LinksGrabberWebParser.LyricsGrabber,而不会隐式导入它们。这可以通过导入__init__.py内的模块来完成,但这是不可能的,因为每个包的模块都会导入包本身,并且它会发出递归导入。

您能建议更好的实施或不同的代码设计吗?

3 个答案:

答案 0 :(得分:1)

您应该通过为app文件提供__init__.py。 python相对导入系统仅在包中使用。然后在WebParser模块中,您可以执行from .. import configfrom .. import Gui等。

至于从其中的软件包导入WebPackage,这有点代码味道。你为什么要那样做?例如,使用相对导入,您可以在ImagesGrabber等中使用from . import LinksGrabber来访问您需要的内容。如果有许多子模块需要的WebParser包的函数,您应该将它们放到WebParser中的单独模块中。

答案 1 :(得分:1)

我会将整个外部(app)目录变成一个python包(带有__ init __。py)。

app_files
  |- ***setup.py***
  |- app
    |- ***__init__.py***
    |- Gui.py
    |- Main.py
    |- logger.py
    |- config.py
    |- WebParser (package)
          |- __init__.py
          |- LinksGrabber.py
          |- LyricsGrabber.py
          |- ImagesGrabber.py
    |- (Many other packages...)

setup.py会像这样简单:

#!/usr/bin/env python

from distutils.core import setup

setup(name='app',
      version='1.0',
      description='My app',
      author='Greg Ward',
      packages=['app'],
     )

然后你可以运行python setup.py install,将'app'永久安装到python路径中。 在我看来,这是最好的方法,无需在任何地方使用sys.path hacks。

然后,从python的任何地方,您都可以参考完整虚线路径中的任何文件

import app.logger
import app.config
import app.WebParser

只需从导入app.WebParser中获取LinksGrabber和LyricsGrabber的唯一方法就是从app.WebParser .__ init __导入它们。

答案 2 :(得分:0)

您似乎可以在这里使用relative imports

from .. import config
from ..logger import log