Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从子包访问共享模块_Python_Code Design_Package Structuring - Fatal编程技术网

Python 从子包访问共享模块

Python 从子包访问共享模块,python,code-design,package-structuring,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...)

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

app
  |- Gui.py
  |- Main.py
  |- logger.py
  |- config.py
  |- WebParser (package)
        |- __init__.py
        |- LinksGrabber.py
        |- LyricsGrabber.py
        |- ImagesGrabber.py
  |- (Many other packages...)
logger.py
config.py
模块在每个包的模块中都是必需的,并且是独立的(仅在模块中使用bulit)。从软件包内部访问这些模块是很棘手的

这就是我试图实现它的方法,在
webpasser\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 webpasser
    并使用
    webpasser.LinksGrabber
    webpasser.LyricsGrabber
    ,而不隐式导入它们。这可以通过导入
    \uuuu init\uuuu.py
    中的模块来完成,但这是不可能的,因为每个包的模块都会导入包本身,并且会发出递归导入

你能推荐一个更好的实现,或者一个不同的代码设计吗?

看起来你可以在这里使用:


你应该给
应用程序一个
\uuuu init\uuuuuu.py
文件,使其成为一个包。python相对导入系统仅在包内工作。然后在WebPasser模块中,您可以从..执行
。。从导入配置
。。导入Gui


至于从其中的包导入网页包,这有点代码味道。你为什么要这么做?例如,使用相对导入,您可以从中获得
。在ImagesGrabber等内部导入LinksGrabber
以访问所需内容。如果WebPasser包中有许多子模块需要的函数,那么应该将这些函数拉到WebPasser中的一个单独模块中。

我会将整个外部(app)目录设置为python包(带有u__; init.py)

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黑客的最好方法

然后,在python中的任何地方,您都可以从满点路径引用任何文件

i、 e


要使LinksGrabber和LyricsGrabber仅从导入app.webpasser中可用,唯一的方法是从app.webpasser中导入它们。u uu; init__;.

当您说“每个模块导入包本身”时,您指的是哪些模块?您的意思是外部目录中的所有模块(配置、Gui等)都导入WebPasser,但WebPasser内部的所有模块也导入这些外部模块吗?或者你的意思是WebPasser内部的模块导入WebPasser本身?我的意思是WebPasser内部的每个模块都导入WebPasser本身。这将不起作用,除非你通过给外部
应用程序
目录一个
\uu init\uuuuuuuuuuuuuuuuupy
@BrenBarn-同意。我想我只是假设这是一个给定的,但也许这是一个坏的假设。。。也许添加
\uuuu init\uuuuuu.py
是OP询问的“更好的实现”;^)。请注意,
app
是否是一个软件包的问题与是否使用
setup.py
在系统范围内安装是分开的。在许多情况下(例如,在开发时),您可能不希望一直使用
setup.py
来安装它。但是,如果您给它一个
\uuuu init\uuuuuuuuuuy.py
,并确保包目录位于系统路径上,那么它就会工作。在开发时,我建议您使用“python setup.py develope”将其安装到系统路径中,并带有(本质上)指向安装目录的符号链接。这样,当您进行更改时,它们会立即传播到系统。BrenBarn所说的是正确的,您不需要setup.py来安装到系统路径上。。。但是任何其他的方法都会让人感觉不舒服。我不确定永久性地将顶级文件夹附加到
PYTHONPATH
中是否正确。问题不在于如何“永久”或“暂时”完成,而在于找到一种不那么老套的方法。相对进口似乎是个更好的主意+不过,这是一种很好的方法。它们不是来自。导入链接标签
和导入链接标签
相同吗?
\uuuu init\uuuu
不应该实现许多子模块所需的功能吗?除了将特定文件夹定义为包之外,我可能不理解
\uuuu init\uuuuuuuuuy.py
文件的用途。
\uuuuuu init\uuuuuuuuuu
应该初始化包。通常它只是一个空文件。有时它会导入特定的子模块,以便在您进行操作时更容易地访问它们。但它并不是真正用于“包范围”通用函数的地方。这些应该在包内的单独模块中。原因正是您所发现的:如果您试图使用
\uuuu init\uuuu
来保存公共函数并导入子模块,但子模块需要公共函数,则会出现循环导入问题。将初始化与常用函数分开。也可将初始化与常用函数分开。如果未启用绝对导入(即,如果没有来自未来导入绝对导入的
),则在Python 2中导入链接rabber
和导入链接rabber
是相同的。如果启用了绝对导入(在Python 3中总是如此),则
import LinksGrabber
将无法工作。另外,请注意来自的
。导入链接Rabber
与导入Web资源不同,这似乎是您所说的。
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...)
#!/usr/bin/env python

from distutils.core import setup

setup(name='app',
      version='1.0',
      description='My app',
      author='Greg Ward',
      packages=['app'],
     )
import app.logger
import app.config
import app.WebParser