我是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)
我正在寻找一种模块化设计,我可以动态地实例化特定的适配器。这些适配器扩展了abc.ABC
中的adapters.__init__
抽象类,它还包含适配器的一些常用实用程序。
非常简单。
问题是各个适配器模块需要引用replicator.sources
中的一些定义。特别是两个班。发生的事情是每个适配器都从第三方获取数据并保护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__
导入某些内容的特定适配器,或者(以某种方式)实际使用adapters
注册replicator
包。它可以从replicator.sources
内wwf_score.py
导入,它出现了。也许这有帮助。
编辑为了清晰度和可读性而进行了更新。
答案 0 :(得分:0)
我找到了一个解决方案,但对于更好的设计仍然存在想法
正如我所料,我的问题是设计不佳而不了解进口。我试图在一些__init__
文件中进行实际定义,并在包外引用这些定义。它导致了意大利面条代码。我最后通过做两件事来解决这个问题:
<强> 1。更小,更清晰的模块
我删除了__init__
文件中的所有定义,并为它们提供了自己的模块。其中一个包括一个装饰器,它是一个可调用类,绑定到 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
一切都很好。
我希望这有助于将来的某些人。我可以自由回答有关我的设置和我发现的问题。
就像我说的,我的一部分问题是我正在做一些复杂的事情 - 一个基于类的装饰器来装饰一个类。这用于将所有个人适配器注册到注册表(和密钥),因此我可以使用工厂来创建它们。
感谢。