【发布时间】:2013-06-29 03:05:55
【问题描述】:
我正在使用 Python 3.3.2 编写一个封装文件系统的包。我的项目如下所示:
~/
python/
filesystem/
__init__.py
file.py
directory.py
PYTHONPATH=~/python.
问题是,file.py需要directory.py(比如File.get_directory()),而directory.py需要file.py(比如Directory.get_files()),所以我有一个循环导入。
- 当我在
file.py中使用import directory和在directory.py中使用import file时,它仅在我的工作目录为filesystem时才有效(即,当导入是本地时)。 - 当我在
file.py中使用import filesystem.directory和在directory.py中使用import filesystem.file时,它工作得很好,除了一直写filesystem.file.File和filesystem.Directory.directory的审美滋扰。 - 奇怪的是,当我使用
import filesystem.directory as directory或from filesystem.directory import Directory时,我收到循环导入错误'module' object has no attribute 'directory'。我的猜测是,虽然import ...很懒惰,但import ... as和from ... import会尝试评估模块并立即注意到循环性。 - 解决这个问题的一种方法是在使用它的函数中
import filesystem.directory。不幸的是,我的许多方法都使用它,并且在类中导入它似乎不起作用。
这当然是可以解决的:把它吸起来,写filesystem.directory.Directory;将__import__ 分配给__init__ 方法中的全局变量,以供所有其他方法使用;在同一个文件中定义File 和Directory;等等。但这些妥协多于解决方案,所以我的问题仍然存在:
- 您将如何设计文件系统,其中文件类使用目录类,反之亦然?
- 更一般地说,您将如何处理(或避免)循环导入?
谢谢。
更新 [03.07.2013](主要是为了讨论)
我遇到的另一个解决方案是某种前向声明,在公共标头中使用空的 file 和 directory 类,然后是单独的实现(更像是属性添加)。虽然最终的设计非常简洁,但这个想法比 Pythonic 更接近 C++。
【问题讨论】:
-
处理循环导入花了我一段时间。我真的必须(手动)将我的模块绘制成树状结构,确保我只携带我的依赖项一个方向。一旦我在做出更大的项目决策之前开始这样做,它确实减少了我以后必须进行的重构。
-
@BlackVegetable - 如果没有循环导入,您将如何设计所描述的文件系统?它在我看来本质上是圆形的,所以我很想听听一些开箱即用的替代设计。
标签: python import system-design