如何使用顶级功能创建PyPi软件包

时间:2019-02-09 21:24:05

标签: python pypi

我正在尝试在PyPi上安装软件包,但无法将其配置为具有所需的语法。归根结底,我希望能够使用以下语法在模块中使用函数:

import ucal
ucal.calculate(...)

此语法遵循所有常见库。 (也可以使用from ucal import calculate)。

我的目录结构如下:

ucal/
    ucal/
        __init__.py
        ucal.py
        ucal_units.py
    setup.py

在ucal.py中:

   import ucal_units
   def calculate():
       pass

我可以上传到PyPi,然后使用pip进行安装:

> python setup.py bdist_wheel
> python -m twine upload dist/ucal-0.1.3-py3-none-any.whl
(wait a minute)
> pip install --user ucal

但是,在新脚本中,以下脚本会产生错误:

import ucal
ucal.calculate() # <-- AttributeError: module 'ucal' has no attribute 'calculate'

事实证明,它可以代替:

from ucal import ucal
ucal.calculate()

但是我不要这种愚蠢的语法。 ucal应该在最高级别。我需要进行哪些更改才能使所需的语法起作用?

我尝试将ucal / ucal中的所有文件都移至父目录,但这即使安装了模块(已通过pip列表验证)也导致ModuleNotFoundError: No module named 'ucal'

2 个答案:

答案 0 :(得分:1)

ucal/ucal.py中,使用__all__变量声明要导出的公共名称:

# ucal/ucal.py

__all__ = ["calculate"]

def calculate(...):
    ...

ucal/__init__.py中,通过使用* import:将这些名称拉入顶级名称空间:

# ucal/__init__.py

from ucal.ucal import *

现在,用户将在顶级名称空间中看到calculate

答案 1 :(得分:0)

在导入时,__init__.py中的名称空间似乎可以通过ucal.*语法进行访问。那么,一种选择是用__init__.py的内容替换ucal.py。这似乎不太正确。

另一种选择是在__init__.py内添加导入语句:

from ucal.ucal import calculate

这似乎也很混乱,但是也许这是公认的做事方式?