【问题标题】:Python: module import hierarchy (non-existing modules at startup)Python:模块导入层次结构(启动时不存在的模块)
【发布时间】:2020-03-16 06:35:18
【问题描述】:

没有快速的方法来描述这个问题,所以请跟我来! A similar question was already asked,但我的用例有点不同。解释它的最简单方法是描述一个实际用例:

我有一个文件夹,其中包含一些常用实用程序模块,我的脚本正在使用这些模块。

commonPythonFiles/
    pathUtils.py
    procUtils.py
    specialModuleUtils.py

    groupedCommonPythonFiles/
        groupUtils1.py
        groupUtils2.py (*)

这些模块可能有交叉导入:procUtils 使用来自pathUtils.py 的函数,而groupUtils1.py 使用它们两者(procUtils.pypathUtils.py)。

有一个特殊的模块,它在脚本开始时不可用 - 它是在 main.py 的运行时通过使用 specialModuleUtils.py 函数提取/复制/生成/...的。

specialModuleFolder/ # not available from the start
    specialModule.py

另一方面,groupUtils2.py (*) 是这样的specialModule.py 的包装器。

在某些工作脚本(例如main.py)中,需要此实用程序模块,因此,它们通常在文件开头导入。


问题

#main.py
import pathUtils
import procUtils
import specialModuleUtils
import groupUtils1
import groupUtils2 # (!)

def main():
    # prepare special module
    args = groupUtils1.getSpecialModuleArguments(sys.argv) # might be a lot more than one line to get arguments
    specialModuleUtils.create(args)

    # do some stuff with groupUtils2 which use created special module
    groupUtils2.doSomeStuffWithSpecialModule()

您可能已经怀疑我面临的问题。我正在导入尚不可用的模块。 main.pyimport groupUtils2 处失败,因为尚未创建 specialModuleUtils

我真正遇到的问题是:处理导入的正确方法是什么,或者一般来说,对于这种非标准情况,最好的模块层次结构是什么?


可能的解决方案

  • 设置规则:公共模块的导入不应放在文件头中。
#main.py
import pathUtils
import procUtils

def main():
    import groupUtils1
    import specialModuleUtils
    # prepare special module
    args = groupUtils1.getSpecialModuleArguments(sys.argv) # might be a lot more than one line to get arguments
    specialModuleUtils.extract(args)

    # do some stuff with groupUtils2 which use created special module
    import groupUtils2
    groupUtils2.doSomeStuffWithSpecialModule()

这会使函数杂乱无章,重复导入语句并使常用实用程序模块的使用变得复杂。

  • 将特殊模块生成作为脚本的先决条件 - main.py 应该在已经准备好的环境中运行,并且可以导入 specialModule.py。 这意味着,在执行任何脚本之前,需要运行一些其他脚本/作业/进程来准备specialModule.py 另外,这个脚本也会限制使用常见的python文件,否则它可能会像main.py一样失败。

由于提取此特殊模块 (args = groupUtils1.getSpecialModuleArguments(sys.argv)) 需要一些逻辑,因此不能选择简单的虚拟环境(或者是吗?)。

:我真正遇到的问题是:处理导入的正确方法是什么,或者一般来说,对于这种非标准情况,最好的模块层次结构是什么?

【问题讨论】:

  • 如何重新评估您的整个设计,以便您在其中一个可以填充的模块中拥有一个普通的 dict,而不是“特殊模块”?无论如何,模块基本上只是一个共享命名空间字典......
  • 也许重新设计会让你摆脱交叉导入。
  • 有许多“通用”文件,因为这允许我们将功能打包到模块中,按功能分组。这样代码就不会重复,这是通用文件的基本思想。 'specialModule'其实也是某种通用文件,但是是版本化的(一些较大软件的python SDK API)-意思是,它通常是从特定路径动态导入的。问题是,添加这个路径很不方便并在某些脚本的最开始处实际动态导入此模块。

标签: python python-3.x hierarchy software-design python-module


【解决方案1】:

当然只有生成文件的导入必须被推迟,或者通过让groupUtils2 仅在其函数内部导入它(或者作为显式初始化步骤,分配导入的模块使用global) 或通过在main 中导入(仅)groupUtils2,一旦它对specialModule 的急切导入可以成功。这些都不是深刻的重组。

【讨论】:

  • 我不确定你的意思是:“(或作为一个显式初始化步骤,为导入的模块分配全局)”。无论如何,在函数中导入模块是否被认为是一种不好的做法?
  • @schperplata:显式初始化将是一个函数groupUtils2.init,它为模块中的所有其他函数执行一次import。函数中的导入很好——它们可能和使用全局导入一样快,并且它们对于限制/延迟依赖关系很有用,尽管它们也会在视觉上分散注意力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-14
  • 1970-01-01
  • 2013-02-20
  • 2019-06-14
  • 2015-01-19
相关资源
最近更新 更多