子包导入 python

Sub package imports with python

我是 python 的新手,但对 PHP 和 JavaScript 非常有经验并且相当熟悉 Java(我几乎每天都使用它们)。我用过 python 的脚本,但直到现在才尝试过大型、复杂的项目。

我很难理解 python 处理包导入的方式。我已经搜索并阅读了其他几个答案,但仍然无法让我的具体案例发挥作用。我想我的错误是由于糟糕的或非 pythonic 设计造成的,但我觉得我正在做的事情在我使用过的其他语言中是一种常见的做法,它应该很简单。

我有以下目录树

+ project (project directory)
    + replicator (source directory)
        + adapters
            - __init__.py 
            - wwf_score.py
            - other_adpater.py (there will be many adapter modules in this package)
        - sources.py
        - __init__.py (empty init for replicator)

我正在寻找一种模块化设计,我可以在其中即时实例化特定的适配器。这些适配器在 adapters.__init__ 中扩展了一个 abc.ABC 抽象 class,它也包含适配器的一些通用实用程序。

很简单。

问题是各个适配器模块需要引用 replicator.sources 中的某些定义。特别是两个 classes。发生的事情是每个适配器都从第三方获取数据并水合一个 RawSource 对象,该对象在 replicator.sources

中定义

wwf_score.py

import replicator.adapters as adapters
import replicator.sources as sources

@adapters.source_adapter
class WWFScoreAdapter(adapters.AbstractAdapter):
    def __init__(self, data):
        self.data = sources.RawData(data)

这会引发一个错误 AttributeError: module 'replicator' has no attribute 'adapters'

我试过向 replicators.__init__ 添加一个导入,并尝试过相对导入和其他一些东西。

我做错了什么?

谢谢大家!

编辑

看来我真正的问题是某个特定的适配器从 adapters.__init__ 导入了一些东西,或者(不知何故)实际上用 replicator 注册了 adapters 包。我可以replicator.sources导入wwf_score.py,它出现了。也许这有帮助。

编辑 为了清晰和可读性而更新。

我找到了解决方案,但仍愿意考虑更好的设计

如我所料,我的问题是设计不佳和不理解导入。我试图在一些 __init__ 文件中进行实际定义,并在包外引用这些定义。它导致了意大利面条代码。我最终通过做两件事解决了这个问题:

1.更小、更清晰的模块 我从 __init__ 文件中删除了所有定义,并为它们提供了自己的模块。其中之一包括一个装饰器,它是一个可调用 class 绑定到 init 文件之外不可用的属性的装饰器。我不确定具体是怎么回事,但我敢肯定这让事情变得很混乱。

我的新结构看起来像这样(如果有人关心的话)

+ project
    + bin
        - replicator.py (script that uses the rest)
    + replicator
        + adapters
            - __init__.py (blank except to import modules)
            - contracts.py (pulled from init, includes Abstract)
            - registry.py (has a class decorator bound to attribute)
            - wwf_score.py (class that extends Abstract)
            - other_adapter.py (another class that extends Abstract)
        - sources.py (the same, just some dtos)
        - __init__.py (empty except for imports)

2。我在包内使用了所有相关导入 所以,我的 wwf_score.py 导入看起来像

from . import contracts
from . import registry
from .. import sources

我的 bin/replicator.py 文件可以通过

引用内容
import replicator.adapters as adapters
import replicator.sources as sources

一切都很好。

我希望这对以后的人有所帮助。我可以自由回答有关我的设置和发现的问题。

就像我说的,我的部分问题是我在做其他复杂的事情——一个基于 class 的装饰器装饰了一个 class。这用于使用注册表(和密钥)注册我所有的个人适配器,因此我可以使用工厂来创建它们。

谢谢。