简体   繁体   English

如何使用顶级函数创建 PyPi 包

[英]How to create PyPi package with top-level functions

I am trying to get a package installed on PyPi and am having trouble getting it configured to have the desired syntax.我正在尝试在 PyPi 上安装一个包,但无法将其配置为具有所需的语法。 At the end of the day, I want to be able to use a function within my module using the following syntax:归根结底,我希望能够使用以下语法在我的模块中使用一个函数:

import ucal
ucal.calculate(...)

This syntax follows all the common libraries.此语法遵循所有公共库。 (One could also use from ucal import calculate ). (也可以使用from ucal import calculate )。

My directory structure is as follows:我的目录结构如下:

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

Within ucal.py:在 ucal.py 中:

   import ucal_units
   def calculate():
       pass

I can upload to PyPi and then install using pip:我可以上传到 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

However, inside a new script, the following script yields an error:但是,在新脚本中,以下脚本会产生错误:

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

It turns out that this works instead:事实证明,这是有效的:

from ucal import ucal
ucal.calculate()

But I don't want this silly syntax.但我不想要这种愚蠢的语法。 ucal should be at the top level. ucal 应该是顶级的。 What changes do I need to make in order to get the desired syntax to work?为了使所需的语法起作用,我需要进行哪些更改?

I tried moving all files in ucal/ucal to the parent directory, but this resulted in ModuleNotFoundError: No module named 'ucal' even though the module was installed (verified with pip list)我尝试将 ucal/ucal 中的所有文件移动到父目录,但这导致ModuleNotFoundError: No module named 'ucal'即使该模块已安装(已通过 pip list 验证)

In ucal/ucal.py , declare public names that you want to export using the __all__ variable:ucal/ucal.py ,使用__all__变量声明要导出的公共名称:

# ucal/ucal.py

__all__ = ["calculate"]

def calculate(...):
    ...

In ucal/__init__.py , pull those names up into the top-level namespace by using the * import:ucal/__init__.py ,使用 * 导入将这些名称拉入顶级命名空间:

# ucal/__init__.py

from ucal.ucal import *

Now, users will see calculate in the top-level namespace.现在,用户将在顶级命名空间中看到calculate

When importing, the namespace within the __init__.py appears to be able to be accessed by the ucal.* syntax.导入时, __init__.py ucal.*的命名空间似乎可以通过ucal.*语法访问。 One option, then, is to replace __init__.py with the contents of ucal.py .那么,一种选择是将__init__.py替换为ucal.py的内容。 This doesn't seem quite correct.这似乎不太正确。

Another option is to add an import statement within __init__.py :另一种选择是在__init__.py添加一个 import 语句:

from ucal.ucal import calculate

This also seems messy, but perhaps that's the accepted way to do things?这似乎也很混乱,但也许这是公认的做事方式?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM