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

时间:2016-10-13 19:58:10

标签: python module package packages python-import

我对如何导入和组织子模块感到有点迷茫,我需要一些文献和一些约定。

问题

我们想要编写一个用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 个答案:

答案 0 :(得分:1)

  

这两种方法都很常见,但它可能污染了pizzafactory命名空间,因此最好是破坏导入名称。我重新认识到没有人这样做,我不知道为什么。

Python是一种同意的成人语言,在大多数情况下,我们将门打开并且所有内容都是公开的。

如果你担心的只是拥挤名称空间,你应该定义__all__以及使用单引导下划线。 - PEP8建议只应使用名称修改来避免命名冲突,这可能是为什么没有人这样做的原因。

请参阅PEP8的Public and internal interfaces部分以及Naming Convensions.

PEP8是"适当"的指南。做这些事情的方法。虽然,它是指南不一定是法律。你可以灵活地做你认为适合你的包装的东西,这导致了我最喜欢的PEP8部分 - A Foolish Consistency is the Hobgoblin of Little Minds

如果没有与包中的代码充分密切,人们可能无法提供超出PEP8的关于如何应该完成的建议。如果你有时间,Raymond Hettinger的演讲Beyond PEP 8值得关注。