如何将自己的Python代码打包发布到pypi上

Python016

如何将自己的Python代码打包发布到pypi上,第1张

什么是pypi

简单的说pypi是一个python包的仓库,里面有很多别人写好的python库,你可以通过easy_install或者pip进行安装,方便用户更方面的使用你的代码模块

将代码打包并上传到pypi上,大体上分为以下几步:

1、整理代码的目录结构,方便打包和python的import,为了方便引用,需要将代码模块变成一个包,所以需要将功能代码用目录来整合方便引用,并且需要创建__init__文件,__init__中可以没有内容,也可以在__init__文件中进行import(from .extractor import Document)操作,以减少整体模块引用时import的层数,避免错误。

[html] view plain copy

├── ./tidypage  

│   ├── ./tidypage/cleaners.py  

│   ├── ./tidypage/extractor.py  

│   ├── ./tidypage/__init__.py  

│   └── ./tidypage/titles.py

2、功能模块的目录整理好后,就可以开始整理和添加发布到pypi上所使用的文件了

tidy_page  

├── LICENSE  

├── README.rst  

├── requirements.txt  

├── setup.py  

├──tidypage  

│   ├──cleaners.py  

│   ├──extractor.py  

│   ├──__init__.py  

│   └──titles.py

就是将原来的目录深移一层,文件夹名称可以根据自己意愿。然后在到第一层的目录下创建些特殊文件,具体你可以看看下面这个文件结构你就明白了

LICENSE文件是授权文件,比如:MIT license, APACHE license

README.rst 文件想必大家都不陌生,其实就是项目介绍和使用说明

setup文件才是重点,是python模块安装所需要的文件,它的格式如下:

#!/usr/bin/env python  

from __future__ import print_function  

from setuptools import setup, find_packages  

import sys  

  

setup(  

    name="tidy-page",  

    version="0.1.1",  

    author="Desion Wang",  

    author_email="[email protected]",  

    description="html text parser,get the content form html page",  

    long_description=open("README.rst").read(),  

    license="MIT",  

    url="https://github.com/desion/tidy_page",  

    packages=['tidypage'],  

    install_requires=[  

        "beautifulsoup4",  

        lxml_requirement  

        ],  

    classifiers=[  

        "Environment :: Web Environment",  

        "Intended Audience :: Developers",  

        "Operating System :: OS Independent",  

        "Topic :: Text Processing :: Indexing",  

        "Topic :: Utilities",  

        "Topic :: Internet",  

        "Topic :: Software Development :: Libraries :: Python Modules",  

        "Programming Language :: Python",  

        "Programming Language :: Python :: 2",  

        "Programming Language :: Python :: 2.6",  

        "Programming Language :: Python :: 2.7",  

    ],  

) NAME 名字,一般放你包的名字即可PACKAGES 包含的包,可以多个,这是一个列表DESCRIPTION 关于这个包的描述LONG_DESCRIPTION 参见read方法说明KEYWORDS 关于当前包的一些关键字,方便PyPI进行分类。AUTHOR 谁是这个包的作者,写谁的名字吧AUTHOR_EMAIL 作者的邮件地址URL 你这个包的项目地址,如果有,给一个吧,没有你直接填写在PyPI你这个包的地址也是可以的VERSION 当前包的版本,这个按你自己需要的版本控制方式来LICENSE 授权方式INSTALL_REQUIRES 模块所依赖的python模块

文中的classifiers的内容并不是随便填写的,你需要参照本文参考文档中的PyPI Classifiers来写

3、开始使用Distutils进行打包

为了保证效果,在打包之前我们可以验证setup.py的正确性,执行下面的代码

python setup.py check

输出一般是running check如果有错误或者警告,就会在此之后显示没有任何显示表示Distutils认可你这个setup.py文件。

如果没有问题,那么就可以正式打包,执行下面的代码:

python setup.py sdist

执行完成后,会在顶层目录下生成dist目录和egg目录

tidy_page  

├── tidy_page/dist  

│   ├── tidy_page/dist/tidy-page-0.1.0.tar.gz  

│   └── tidy_page/dist/tidy-page-0.1.1.tar.gz  

├── tidy_page/LICENSE  

├── tidy_page/README.rst  

├── tidy_page/setup.py  

├── tidy_page/tidypage  

│   ├── tidy_page/tidypage/cleaners.py  

│   ├── tidy_page/tidypage/extractor.py  

│   ├── tidy_page/tidypage/__init__.py  

│   └── tidy_page/tidypage/titles.py  

├── tidy_page/tidy_page.egg-info  

│   ├── tidy_page/tidy_page.egg-info/dependency_links.txt  

│   ├── tidy_page/tidy_page.egg-info/PKG-INFO  

│   ├── tidy_page/tidy_page.egg-info/requires.txt  

│   ├── tidy_page/tidy_page.egg-info/SOURCES.txt  

│   └── tidy_page/tidy_page.egg-info/top_level.txt

4、打包完成后就可以准备将打包好的模块上传到pypi了,首先你需要在pypi上进行注册 goto PyPI Live

注册完成后,你需要在本地创建好pypi的配置文件,不然有可能会出现使用http无法上传到pypi的问题

Create a .pypirc configuration file,在用户的home目录下创建.pypirc文件,文件的内容如下

[distutils]index-servers =  pypi[pypi]repository=https://pypi.python.org/pypiusername=your_usernamepassword=your_passwor chmod 600 ~/.pypirc

python setup.py register -r pypi

在pypi上注册模块

python setup.py sdist upload -r pypi

上传python文件包,没有问题你就可以在pypi上看到你上传的包了并且可以使用pip搜索和install你的python包了

使用pip或easy_install可以管理和安装python的package包,实际上它们都是从pypi服务器中搜索和下载package的。目前在pypi服务器上,有超过三万多个package,同时还允许我们将自己的代码也上传发布到服务器上。这样,世界上的所有人都能使用pip或easy_install来下载使用我们的代码了。具体步骤如下:首先创建项目文件和setup文件。目录文件结构如下:project/simpletest/__init__.pytest.pysetup.py假设项目文件只有一个simpletest包,里面有一个test.py文件。创建的setup.py文件格式大致如下,其中,install_requires字段可以列出依赖的包信息,用户使用pip或easy_install安装时会自动下载依赖的包。详细的格式参考文档。from setuptools import setup, find_packagessetup(name = 'simpletest',version = '0.0.1',keywords = ('simple', 'test'),description = 'just a simple test',license = 'MIT License',install_requires = ['simplejson>=1.1'],author = 'yjx',author_email = '[email protected]',packages = find_packages(),platforms = 'any',)然后将代码打包。打包只需要执行pythonsetup.py xxx命令即可,其中xxx是打包格式的选项,如下:# 以下所有生成文件将在当前路径下 dist 目录中python setup.py bdist_egg # 生成easy_install支持的格式 python setup.py sdist # 生成pip支持的格式,下文以此为例发布到pypi。发布到pypi首先需要注册一个账号,然后进行如下两步:注册package。输入python setup.py register。上传文件。输入python setup.py sdist upload。安装测试上传成功后,就可以使用pip来下载安装了。另外,pypi还有一个测试服务器,可以在这个测试服务器上做测试,测试的时候需要给命令指定额外的"-r"或"-i"选项,如pythonsetup.py register -r "",pythonsetup.py sdist upload -r "",pipinstall -i "" simpletest。发布到测试服务器的时候,建议在linux或cygwin中发布,如果是在windows中,参考文档,需要生成.pypirc文件

包(packages)其实也是模块,其类型Type也是module。通常引用自定义模块时有两种方法:

1)将两个文件放在同一目录下。

2)在sys.path下添加要引用的py文件的路径。然后import。

这样的做法,对于少数文件是可行的,但如果程序数目很多,层级很复杂时就比较麻烦了。此时用package就能将多个py文件组织起来,类似于第三方包一样的引用。要方便很多。

package的层次结构与程序所在目录的层次结构相同,且必须包含一个__init__.py的文件。__init__.py可以为空,只要它存在就表明此目录被作为一个package处理。

package1/

__init__.py

subPack1/

__init__.py

module_11.py

module_12.py

module_13.py

subPack2/

__init__.py

module_21.py

module_22.py

……

__init__.py可以为空,只要它存在,就表明此目录应被作为一个package处理。当然,__init__.py中也可以设置相应的内容。

好了,现在我们在module_11.py中定义一个函数:

def funA():

print "funcA in module_11"

return

一.引用模块

在顶层目录(也就是package1所在的目录,当然也参考上面的介绍,将package1放在解释器能够搜索到的地方)运行python:

>>>from package1.subPack1.module_11 import funcA

>>>funcA()

funcA in module_11

这样,我们就按照package的层次关系,正确调用了module_11中的函数。

二.使用通配符*,导入某个module中的所有元素

答案就在__init__.py中。我们在subPack1的__init__.py文件中写

__all__ = ['module_13', 'module_12']

然后进入python

>>>from package1.subPack1 import *

>>>module_11.funcA()

Traceback (most recent call last):

File "", line 1, in

ImportError: No module named module_11

也就是说,以*导入时,package内的module是受__init__.py限制的。

三.在package内部互相调用。

1.如果希望调用同一个package中的module,则直接import即可。也就是说,在module_12.py中,可以直接使用

import module_11

2.如果不在同一个package中,例如我们希望在module_21.py中调用module_11.py中的FuncA,则应该这样:

from module_11包名.module_11 import funcA

四.Python如何找到我们定义的module?

在标准包sys中path属性记录了Python的包路径。

import sys

print(sys.path)

通常我们可以将module的包路径放到环境变量PYTHONPATH中,该环境变量会自动添加到sys.path属性.

另一种方便的方法是编程中直接指定我们的module路径到sys.path 中。

常用的话也可以放在python27\lib\site-packages文件夹下。