【问题标题】:How do I structure Python code into modules/packages?如何将 Python 代码构造成模块/包?
【发布时间】:2010-10-20 16:44:00
【问题描述】:

假设我有这个准系统结构:

project/
  main.py
  providers/
    __init.py__
    acme1.py
    acme2.py
    acme3.py
    acme4.py
    acme5.py
    acme6.py

假设main.py 包含(部分):

if complexcondition():
  print providers.acme5.get()

其中__init__.py 为空且acme*.py 包含(部分):

def get():
  value=complexcalculation()
  return value

如何更改这些文件才能正常工作?

注意:如果答案是 __init__.py 中的“import acme1”、“import acme2”等,有没有办法在不手动列出它们的情况下完成?

【问题讨论】:

标签: python module package


【解决方案1】:

嘿!两年后但...也许对某人有帮助

让你的 providers/__init__.py 像这样:

import os
import glob

module_path = os.path.dirname(__file__)
files = glob.glob(os.path.join(module_path, 'acme*.py'))
__all__ = [os.path.basename(f)[:-3] for f in files]

如果添加或删除任何 providers/acme*.py

,您以后不必更改它

然后在 ma​​in.py

中使用from providers import *

【讨论】:

  • 这引入了“魔法”;即意想不到的副作用。文件的存在不应导致代码执行。这违背了最小意外的原则,使这是一个坏主意(tm)。 -1
  • @koert 有点魔法有什么问题? :P 在这种情况下,问题是:“有没有办法在不手动列出它们的情况下实现这一点?”......我认为他要求的是一点魔法。也许文件是自动生成的,他不想在每次出现新代码时都编辑他的代码。没有魔法你怎么能做到这一点?
  • 你是对的,没有魔法就无法完成你的场景。另一方面,这种魔法是系统管理员地狱的开始(去过那里,做过那个)。
【解决方案2】:

如果我正确阅读了您的问题,那么您似乎并没有尝试进行任何动态导入(就像 Van Gale 提到的问题中一样),但实际上只是尝试导入 providers 包中的所有模块.如果是这样的话,在__init__.py 你会想要这样的声明:

__all__ = ["acme1", "acme2", "acme3", "acme4", "acme5", "acme6"]

然后导入您将使用的所有内容 from ... import *

from providers import *

然后,您只需调用导入的类,而不是在代码中显式使用包名

acme1.get()
acme2.get()

如果提供程序包中有足够多的模块,以至于填充__all__ 列表成为问题,您可能需要考虑将它们分解为更小的包或以其他方式存储数据。我个人不希望每次我想重用包时都必须处理动态导入 schennagins。

【讨论】:

    【解决方案3】:

    今天问的这个问题,Dynamic Loading of Python Modules,应该会有你的答案。

    【讨论】:

    • 不是我所希望的,但它让我找到了一个可行的解决方案,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-01
    • 2021-02-16
    • 2021-03-10
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    相关资源
    最近更新 更多