How to write a Python module/package?
我一直在为工作中的简单任务制作Python脚本,从来没有真正费心打包它们供其他人使用。现在我被指派为RESTAPI制作一个Python包装器。我完全不知道如何开始,我需要帮助。
我所拥有的:
(只想尽可能具体)我已经准备好了virtualenv,它也在Github中,还有用于python的.gitignore文件,另外还有用于与REST API交互的请求库。就是这样。
这是当前目录树
1 2 3 4 5 6 7 8 9 10 11 12 13 | . ├── bin │ └── /the usual stuff/ ├── include │ └── /the usual stuff/ ├── lib │ └── python2.7 │ └── /the usual stuff/ ├── local │ └── /the usual stuff/ └── README.md 27 directories, 280 files |
我甚至不知道把.py文件放在哪里,如果我做过.py文件的话。
我想做的是:
使用"pip install…"使python模块可以安装。
如果可能的话,我希望有一个关于编写Python模块的一般步骤。
模块是包含Python定义和语句的文件。文件名是后缀为
创建
1 2 | def helloworld(): print"hello" |
然后可以导入
1 2 3 4 | >>> import hello >>> hello.helloworld() 'hello' >>> |
将多个
1 2 3 | |-HelloModule |_ __init__.py |_ hellomodule.py |
您可以按照通常的方式在模块上使用import语句。
有关更多信息,请参见6.4。包装。
python 3-2015年11月18日更新
发现公认的答案是有用的,但希望根据我自己的经验,为他人的利益扩展几点。
模块:模块是包含Python定义和语句的文件。文件名是附加后缀.py的模块名。
模块示例:假设当前目录中只有一个python脚本,这里我将其命名为mymodule.py。
mymodule.py文件包含以下代码:
1 2 | def myfunc(): print("Hello!") |
如果我们从当前目录运行python3解释器,我们可以通过以下不同的方式导入和运行函数myfunc(您通常只需选择以下方法之一):
1 2 3 4 5 6 7 8 9 | >>> import mymodule >>> mymodule.myfunc() Hello! >>> from mymodule import myfunc >>> myfunc() Hello! >>> from mymodule import * >>> myfunc() Hello! |
好吧,那就简单多了。
现在假设您需要将这个模块放到它自己的专用文件夹中,以提供一个模块名称空间,而不只是从当前工作目录临时运行它。这是一个值得解释包装概念的地方。
包:包是通过使用"点式模块名称"来构造Python模块名称空间的一种方法。例如,模块名a.b在名为a的包中指定名为b的子模块。就像使用模块可以避免不同模块的作者担心彼此的全局变量名一样,使用点状模块名可以避免多模块包(如numpy或python imaging library)的作者必须担心彼此的模块名。
包示例:现在假设我们有以下文件夹和文件。在这里,mymodule.py与之前的完全相同,并且uu init_uuu.py是一个空文件:
1 2 3 4 | . └── mypackage ├── __init__.py └── mymodule.py |
为了让python将目录视为包含包,需要使用u init .py文件。有关更多信息,请参阅稍后提供的模块文档链接。
我们当前的工作目录比名为mypackage的普通文件夹高一级。
1 2 | $ ls mypackage |
如果现在运行python3解释器,我们可以通过以下不同的方式导入和运行包含所需函数myfunc的模块mymodule.py(通常只选择以下一种方式):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | >>> import mypackage >>> from mypackage import mymodule >>> mymodule.myfunc() Hello! >>> import mypackage.mymodule >>> mypackage.mymodule.myfunc() Hello! >>> from mypackage import mymodule >>> mymodule.myfunc() Hello! >>> from mypackage.mymodule import myfunc >>> myfunc() Hello! >>> from mypackage.mymodule import * >>> myfunc() Hello! |
假设使用python 3,在:modules中有很好的文档
在包和模块的命名约定方面,PEP-0008中给出了通用指南-请参阅包和模块名称
模块应该有所有小写的短名称。如果下划线提高了可读性,则可以在模块名称中使用下划线。尽管不鼓励使用下划线,但python包也应该有短的、全小写的名称。
因为还没有人讨论过这个行动的问题:
What I wanted to do:
Make a python module install-able with"pip install ..."
这里是一个绝对最小的例子,展示了使用
这绝不是至少阅读教程的替代品,它比这个非常基本的例子所涵盖的要多得多。
创建包本身已经包含在这里的其他答案中,所以让我们假设我们已经包含了这个步骤,并且我们的项目结构如下:
1 2 3 4 | . └── hellostackoverflow/ ├── __init__.py └── hellostackoverflow.py |
为了使用
1 2 3 4 5 | . ├── setup.py └── hellostackoverflow/ ├── __init__.py └── hellostackoverflow.py |
我们至少为包指定元数据,我们的
1 2 3 4 5 6 7 8 9 10 11 12 13 | from setuptools import setup setup( name='hellostackoverflow', version='0.0.1', description='a pip-installable package example', license='MIT', packages=['hellostackoverflow'], author='Benjamin Gerfelder', author_email='[email protected]', keywords=['example'], url='https://github.com/bgse/hellostackoverflow' ) |
由于我们已经设置了
1 2 3 4 5 6 7 | . ├── LICENCE.txt ├── README.rst ├── setup.py └── hellostackoverflow/ ├── __init__.py └── hellostackoverflow.py |
此时,我们准备开始使用
1 | pip install setuptools |
为了做到这一点并创建一个
1 | python setup.py sdist |
这将创建我们的分发包和蛋信息,并产生这样的文件夹结构,我们的包位于
1 2 3 4 5 6 7 8 9 | . ├── dist/ ├── hellostackoverflow.egg-info/ ├── LICENCE.txt ├── README.rst ├── setup.py └── hellostackoverflow/ ├── __init__.py └── hellostackoverflow.py |
此时,我们有一个可以使用
1 | pip install ./dist/hellostackoverflow-0.0.1.tar.gz |
如果一切顺利的话,我们现在可以打开一个python解释器了,我会在项目目录之外的某个地方说,以避免混淆,并尝试使用我们闪亮的新包:
1 2 3 4 5 6 | Python 3.5.2 (default, Sep 14 2017, 22:51:06) [GCC 5.4.0 20160609] on linux Type"help","copyright","credits" or"license" for more information. >>> from hellostackoverflow import hellostackoverflow >>> hellostackoverflow.greeting() 'Hello Stack Overflow!' |
现在,我们已经确认了包的安装和工作,我们可以将其上传到pypi。
由于我们不想用我们的实验来污染实时存储库,因此我们为测试存储库创建一个帐户,并为上载过程安装
1 | pip install twine |
现在我们就快到了,创建了我们的帐户后,我们只需告诉
1 | twine upload --repository-url https://test.pypi.org/legacy/ dist/* |
我们现在可以登录PYPI测试存储库的帐户,对我们刚上传的包感到惊奇一段时间,然后使用
1 | pip install --index-url https://test.pypi.org/simple/ hellostackoverflow |
如我们所见,基本过程并不十分复杂。正如我前面所说,它比这里介绍的内容要多得多,所以继续阅读教程以获得更深入的解释。
一旦定义了所选的命令,就可以简单地将保存的文件拖放到Python程序文件中的lib文件夹中。
1 2 | >>> import mymodule >>> mymodule.myfunc() |
制作一个名为"hello.py"的文件
如果您使用的是python 2.x
1 2 | def func(): print"Hello" |
如果您使用的是python 3.x
1 2 | def func(): print("Hello") |
运行文件。然后,您可以尝试以下操作:
1 2 3 | >>> import hello >>> hello.func() Hello |
如果你想要有点困难,可以使用以下方法:
如果您使用的是python 2.x
1 2 | def say(text): print text |
如果您使用的是python 3.x
1 2 | def say(text): print(text) |
看到define旁边括号里的那个吗?这很重要。它可以在定义中使用。
文本-当你想让程序说出你想要的内容时,你可以使用它。根据它的名字,它是文本。我希望你知道课文的意思。它的意思是"单词"或"句子"。
运行文件。然后,如果您使用的是python 3.x,则可以尝试以下操作:
1 2 3 4 5 6 | >>> import hello >>> hello.say("hi") hi >>> from hello import say >>> say("test") test |
对于python 2.x-我猜和python 3一样?不知道。如果我在python 2.x上犯了错误,请纠正我(我知道python 2,但我习惯于python 3)
我创建了一个项目来轻松地从头开始一个项目框架。https://github.com/machu-gwu/pygitrepo-project.
你可以创建一个测试项目,比如说,
您可以了解为不同的目的应该拥有什么组件,例如:
- 创建virtualenv
- 安装本身
- 运行统一测试
- 运行代码覆盖率
- 构建文档
- 部署文档
- 在不同的python版本中运行unittest
- 部署到PyPI
使用
这是一个学习像专业人员一样开发Python项目的好地方。
希望这能有所帮助。
谢谢您。