如何正确地导入Python包中的子模块?

4

我对如何导入和组织我的子模块有些迷茫,需要一些文献和一些惯例。

问题

我们想编写一个用Python编写的新软件包,它由几个组件组成:

  • 对最终用户有用的类和函数
  • 很少使用的类和函数
  • 仅被软件包本身需要的实用程序类和函数
  • 外部模块

我们考虑这种架构:

pizzafactory
├── __init__.py
├── salt.py 
├── water.py 
├── vegetables
│   ├── __init__.py 
│   └── tomatoes.py 
└── dough
    ├── __init__.py 
    └── flour.py 

一些考虑因素

  • 最终用户不需要使用原材料,如面团或水
  • 客户只需要在 pizzafactory/__init__.py 中描述的披萨
  • 面团工厂需要盐和水
  • 客户可能想在他的披萨上添加一些番茄。

文件pizzafactory/__init__.py几乎需要所有模块,但因为我们不想用无用的东西污染最终用户的命名空间。我建议安静地导入原材料,除了那些可能被客户使用的原材料:

# pizzafactory/__init__.py
import salt as _salt
import dough as _dough
import vegetables.tomatoes

import oven as _oven # External package

制作面团的工厂需要一些水,但需要使用该子模块(制作面包)的用户可能不想看到 water

# pizzafactory/dough/__init__.py
import pizzafactory.water as _water

讨论

首先,我认为直接导入全部内容是更容易的选择,可以使用完整的包:

import pizzafactory

def grab_tomato():
    return pizzafactory.vegetables.tomatoes.BeefsteakTomato()

或者只选择所需元素:
from pizzafactory.vegetables.tomatoes import BeefsteakTomato

def grab_tomato():
    return BeefsteakTomato()

这两种方法都很常见,但它们可能会污染 pizzafactory 命名空间,因此最好使用导入名称混淆。我意识到没有人这样做,但我不知道为什么。

问题

在这个通用示例中,我想知道如何正确地导入模块、子模块和外部包,以便:

  • 最小化命名空间占用
  • 帮助最终用户清楚地看到他只需要使用的内容
1个回答

1

这两种方法都很常见,但可能会污染pizzafactory命名空间,因此最好对导入名称进行修改。我意识到没有人这样做,但不知道为什么。

Python是一种成熟的语言,我们将所有东西都敞开了,大部分情况下。如果你只是担心命名空间过于拥挤,应该定义__all__并使用单个前导下划线。--PEP8建议仅在避免命名冲突时使用名称修饰,这可能就是为什么没有人这样做的原因。

请参阅PEP8的公共和内部接口部分以及命名约定

PEP8是关于这些事情“正确”做法的指南。尽管它只是一个指南,而不一定是法律。您有灵活性来做您认为适合您的软件包的事情,这导致我最喜欢的PEP8部分是 A Foolish Consistency is the Hobgoblin of Little Minds
如果没有足够亲密地了解软件包中的代码,除了PEP8之外,可能无法提供太多建议,说明应该如何完成。如果您有时间,Raymond Hettinger的演讲 Beyond PEP 8值得一看。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接