如何编写Python模块/包?

时间:2013-04-01 15:48:53

标签: python python-2.7 python-module

我一直在为工作中的简单任务制作Python脚本,从来没有真正打扰包装它们以供其他人使用。现在我被分配为REST API创建一个Python包装器。我完全不知道如何开始,我需要帮助。

我有什么:

(只是想尽可能具体)我准备好了virtualenv,它也是up in github,python的.gitignore文件也是,加上requests library for与REST API交互。就是这样。

这是当前目录树

.
├── 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文件放在哪里,如果我做的话。

我想做什么:

使用“pip install ...”安装一个python模块

如果可能的话,我想要一步一步地编写Python模块。

7 个答案:

答案 0 :(得分:383)

模块是包含Python定义和语句的文件。文件名是带有后缀.py

的模块名称

创建hello.py,然后将以下函数编写为其内容:

def helloworld():
   print "hello"

然后您可以导入hello

>>> import hello
>>> hello.helloworld()
'hello'
>>>

要将许多.py个文件分组,请将它们放在一个文件夹中。具有__init__.py的任何文件夹都被python视为模块,您可以将它们称为包

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

您可以通常的方式在模块上使用import语句。

有关详细信息,请参阅6.4. Packages

答案 1 :(得分:207)

Python 3 - 2015年11月18日更新

发现已接受的答案很有用,但希望根据我自己的经验扩展其他几个方面以造福他人。

模块:模块是包含Python定义和语句的文件。文件名是附加后缀.py的模块名称。

模块示例:假设我们在当前目录中有一个python脚本,这里我称之为 mymodule.py

文件 mymodule.py 包含以下代码:

def myfunc():
    print("Hello!")

如果我们从当前目录运行python3解释器,我们可以通过以下不同方式导入并运行函数 myfunc (通常只选择以下一种方法):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

好的,这很容易。

现在假设您需要将此模块放入其自己的专用文件夹中以提供模块命名空间,而不是仅从当前工作目录中临时运行它。这是值得解释的概念的地方。

:包是一种使用“点模块名称”构建Python模块命名空间的方法。例如,模块名称AB在名为A的包中指定名为B的子模块。就像使用模块保存不同模块的作者不必担心彼此的全局变量名一样,使用点模块名称可以保存作者NumPy或Python Imaging Library等多模块软件包不必担心彼此的模块名称。

包示例:现在我们假设我们有以下文件夹和文件。在这里, mymodule.py 与之前相同, __ init __。py 是一个空文件:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

需要__init__.py文件才能使Python将目录视为包含包。有关详细信息,请参阅稍后提供的模块文档链接。

我们当前的工作目录比名为 mypackage

的普通文件夹高一级
$ ls
mypackage

如果我们现在运行python3解释器,我们可以通过以下不同的方式导入并运行包含所需函数 myfunc 的模块 mymodule.py (通常只会选择以下之一):

>>> 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中给出了一般准则 - 请参阅Package and Module Names

模块应该有简短的全小写名称。如果提高可读性,则可以在模块名称中使用下划线。 Python包也应该有简短的全小写名称,但不鼓励使用下划线。

答案 2 :(得分:157)

由于没有人确实涵盖OP的这个问题:

  

我想做什么:

     

使用“pip install ...”安装一个python模块

这是一个绝对最小的示例,显示了使用setuptoolstwine准备包并将其上传到PyPI的基本步骤。

这绝不是reading at least the tutorial的替代品,除了这个非常基本的例子外,还有更多内容。

创建包本身已经包含在其他答案中了,所以让我们假设我们已经涵盖了这一步,我们的项目结构如下:

.
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

为了使用setuptools进行打包,我们需要添加一个文件setup.py,这将进入我们项目的根文件夹:

.
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

至少,我们指定了包的元数据,我们的setup.py将如下所示:

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='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

由于我们已设置license='MIT',因此我们将项目中的副本LICENCE.txt与reStructuredText中的自述文件一起列为README.rst

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

此时,我们已准备好使用setuptools开始打包,如果我们尚未安装,我们可以使用pip进行安装:

pip install setuptools

为了做到这一点并创建source distribution,我们在项目根文件夹中从命令行调用setup.py,指定我们想要sdist

python setup.py sdist

这将创建我们的分发包和egg-info,并产生这样的文件夹结构,我们的包在dist中:

.
├── dist/
├── hellostackoverflow.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

此时,我们有一个可以使用pip安装的软件包,因此从我们的项目根目录开始(假设您拥有此示例中的所有命名):

pip install ./dist/hellostackoverflow-0.0.1.tar.gz

如果一切顺利,我们现在可以打开一个Python解释器,我会说在项目目录之外的某处,以避免任何混淆,并尝试使用我们闪亮的新包:

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。

由于我们不希望通过实验污染实时存储库,因此我们为testing repository创建了一个帐户,并为上传过程安装了twine

pip install twine

现在我们差不多了,创建了我们的帐户,我们只是告诉twine上传我们的包,它会要求我们的凭据并将我们的包上传到指定的存储库:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

我们现在可以在PyPI测试存储库上登录我们的帐户,并对我们刚刚上传的软件包感叹一段时间,然后使用pip抓住它:

pip install --index-url https://test.pypi.org/simple/ hellostackoverflow

我们可以看到,基本过程并不复杂。正如我之前所说,这里有很多内容,所以请继续read the tutorial进行更深入的解释。

答案 3 :(得分:9)

一旦定义了所选命令,就可以将保存的文件拖放到python程序文件的Lib文件夹中。

>>> import mymodule 
>>> mymodule.myfunc()

答案 4 :(得分:4)

制作名为“hello.py”的文件

如果您使用的是Python 2.x

def func():
    print "Hello"

如果您使用的是Python 3.x

def func():
    print("Hello")

运行该文件。然后,您可以尝试以下方法:

>>> import hello
>>> hello.func()
Hello

如果您想要一点点努力,可以使用以下内容:

如果您使用的是Python 2.x

def say(text):
    print text

如果您使用的是Python 3.x

def say(text):
    print(text)

请参阅define旁边的括号中的一个?这很重要。它是您可以在定义中使用的那个。

文本 - 当您希望程序说出您想要的内容时,可以使用它。根据它的名字,它是文字。我希望你知道文字是什么意思。它的意思是“单词”或“句子”。

运行该文件。然后,如果您使用的是Python 3.x,则可以尝试以下操作:

>>> 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中使用)

,请纠正我

答案 5 :(得分:1)

我创建了一个项目,以轻松地从头开始创建项目框架https://github.com/MacHu-GWU/pygitrepo-project

您可以创建一个测试项目,例如learn_creating_py_package

您可以了解具有不同用途的组件,例如

  • 创建virtualenv
  • 自行安装
  • 运行unittest
  • 运行代码覆盖范围
  • 构建文档
  • 部署文档
  • 在不同的python版本中运行unittest
  • 部署到PYPI

使用pygitrepo的优势在于,那些乏味的代码会自动创建并适应您的package_nameproject_namegithub_accountdocument host service,{{1 }}。

这是学习开发像专家这样的python项目的好地方。

希望这会有所帮助。

谢谢。

答案 6 :(得分:0)

模块是一个包含Python定义和语句的文件。文件名是带有后缀.py

的模块名称。

创建一个名为hello.py的文件,其内容如下:

def helloworld():
   print "hello"

那么你可以

import hello
hello.helloworld()

要对许多.py文件进行分组,请将它们放在一个文件夹中。带有 init .py的任何文件夹都被python视为模块,您可以将其称为包。

| -HelloModule | _ init .py | _ hellomodule.py