写给程序员的Python教程笔记13——打包与分发

附录 B 打包与分发

        本节介绍如何使用标准的distutils模块打包。

        distutils模块允许编写简单的Python脚本,该脚本知道如何将Python模块安装到任何Python的安装目录中,包括托管在一个虚拟环境中。按照惯例,这个脚本叫做setup.py,它位于项目结构的顶层。可以执行这个脚本进行实际的安装。

B.1 使用distutils配置一个包

        下面是一个distutils的简单例子。将为在第11章缩写的palindrome模块创建一个基本的setup.py安装脚本。

        首先,创建一个目录来保存项目。该目录名为palindrome,在这个目录中放一份palindrome.py的副本:

""" palindrome.py - 检测回文数字 """

import unittest

def digits(x):
    """将整数转换为数字列表。
    
    Args:
        x:我们想要的数字
    Returns:数字列表,按照“x”的顺序排列。

    >>> digits(4586378)
    [4, 5, 8, 6, 3, 7, 8]
    """
    digs = []
    while x != 0:
        div, mod = divmod(x, 10)
        digs.append(mod)
        x = div
    return digs[::-1]


def is_palindrome(x):
    """确定一个整数是否是回文。
    
    Args:
        x:需要进行回文检查的数字。
    Returns:如果数字“x”是回文数字就返回True,否则返回False。

    >>> is_palindrom(1234)
    False
    >>> is_palindrom(2468642)
    True
    """
    digs = digits(x)
    for f, r in zip(digs, reversed(digs)):
        if f != r:
            return False
    return True


class Tests(unittest.TestCase):
    """''is_Palindrom()''函数的测试"""
    def test_negative(self):
        """检查结果为错误返回False。"""
        self.assertFalse(is_palindrome(1234))

    def test_positive(self):
        """检查结果为正确返回True。"""
        self.assertTrue(is_palindrome(1234321))

    def test_single_digit(self):
        """对于一位数字,检查能正常运行。"""
        for i in range(10):
            self.assertTrue(is_palindrome(i))

if __name__ == '__main__':
    unittest.main()            

        最后创建一个setup.py脚本:

from distutils.core import setup

setup(
    name='palindrome',
    version='1.0',
    py_modules=['palindrome'],
    # metadata
    author='Austin Bingham',
    # author_email =
    description='A module for finding palindromic integers.',
    license='Public domain',
    keywords='palindrome',)

        文件第一行从distutils.core模块导入setup()函数。这个函数完成所有的安装代码的工作,我们通过向函数传递参数来告诉它。

        我们告诉setup()的第一件事就是这个项目的名字。一般来说,最简单的办法就是保持名称与项目的名称相同。

        下一个参数是版本。它可以是任何你想要的字符串,Python不依赖于版本来遵循任何规则。

        参数py_modules可能是最令人关注的。用它来指定想要安装的Python模块。此列表中的每个条目都是不带.py扩展名的模块名称。setup()将查找匹配的.py文件并进行安装。

        其它的参数是不言自明的,主要是为了帮助你正确地使用模块,并知道如果有问题要联系谁。

        在开始使用setup.py之前,首先要创建一个虚拟环境,并将模块安装到该环境中。在palindrome目录中,创建一个qkylpalindrome_env的虚拟环境:

D:\python\写给程序员的Python教程\pyfund\palindrome>python -m venv palindrome
_env

        创建完成后,就可以激活这个新的的环境了。在Linux系统或MacOS系统上,寻找这个激活脚本的源:

$ source palindrome_env/Scripts/activate

        在Windows系统上直接调用这个脚本:

D:\python\写给程序员的Python教程\pyfund\palindrome>palindrome_env\Scripts\activate

B.2 使用distutils安装

        下面将这个模块安装到虚拟环境中。通过将install参数传递给setup.py来完成此操作:

(palindrome_env) D:\python\写给程序员的Python教程\pyfund\palindrome>python setup.py install
running install
D:\python\写给程序员的Python教程\pyfund\palindrome\palindrome_env\Lib\site-packages\setuptools\command\install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
  warnings.warn(
D:\python\写给程序员的Python教程\pyfund\palindrome\palindrome_env\Lib\site-packages\setuptools\command\easy_install.py:144: EasyInstallDeprecationWarning: easy_install command is deprecated. Use build and pip and other standards-based tools.
  warnings.warn(
running bdist_egg
running egg_info
creating palindrome.egg-info
writing palindrome.egg-info\PKG-INFO
writing dependency_links to palindrome.egg-info\dependency_links.txt
writing top-level names to palindrome.egg-info\top_level.txt
writing manifest file 'palindrome.egg-info\SOURCES.txt'
reading manifest file 'palindrome.egg-info\SOURCES.txt'
writing manifest file 'palindrome.egg-info\SOURCES.txt'
installing library code to build\bdist.win-amd64\egg
running install_lib
running build_py
creating build
creating build\lib
copying palindrome.py -> build\lib
creating build\bdist.win-amd64
creating build\bdist.win-amd64\egg
copying build\lib\palindrome.py -> build\bdist.win-amd64\egg
byte-compiling build\bdist.win-amd64\egg\palindrome.py to palindrome.cpython-311.pyc
creating build\bdist.win-amd64\egg\EGG-INFO
copying palindrome.egg-info\PKG-INFO -> build\bdist.win-amd64\egg\EGG-INFO
copying palindrome.egg-info\SOURCES.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying palindrome.egg-info\dependency_links.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying palindrome.egg-info\top_level.txt -> build\bdist.win-amd64\egg\EGG-INFO
zip_safe flag not set; analyzing archive contents...
creating dist
creating 'dist\palindrome-1.0-py3.11.egg' and adding 'build\bdist.win-amd64\egg' to it
removing 'build\bdist.win-amd64\egg' (and everything under it)
Processing palindrome-1.0-py3.11.egg
Copying palindrome-1.0-py3.11.egg to d:\python\写给程序员的python教程\pyfund\palindrome\palindrome_env\lib\site-packages
Adding palindrome 1.0 to easy-install.pth file

Installed d:\python\写给程序员的python教程\pyfund\palindrome\palindrome_env\lib\site-packages\palindrome-1.0-py3.11.egg
Processing dependencies for palindrome==1.0
Finished processing dependencies for palindrome==1.0

        当调用setup()时,它会输出几行信息来报告进度。对于我们来说最重要的是将palindrome.py复制到安装文件夹中:

creating build
creating build\lib
copying palindrome.py -> build\lib
creating build\bdist.win-amd64
creating build\bdist.win-amd64\egg
copying build\lib\palindrome.py -> build\bdist.win-amd64\egg
byte-compiling build\bdist.win-amd64\egg\palindrome.py to palindrome.cpython-311.pyc

creating build\bdist.win-amd64
creating build\bdist.win-amd64\egg

creating dist
creating 'dist\palindrome-1.0-py3.11.egg' and adding 'build\bdist.win-amd64\egg' to it

Copying palindrome-1.0-py3.11.egg to d:\python\写给程序员的python教程\pyfund\palindrome\palindrome_env\lib\site-packages

        第三方软件包,例如模块,通常安装在Python安装目录的site-packages目录中。所以安装工作看起来是正常的。

        下面运行Python来验证这一点,并看一下模块如何被导入。请注意,我们希望在执行此操作之前可以更改目录,否则当导入palindrome时,Python将简单地将源文件加载到当前目录中:

(palindrome_env) D:\python\写给程序员的Python教程\pyfund\palindrome>cd d:\

(palindrome_env) d:\>python
Python 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import palindrome
>>> palindrome.__file__
'D:\\python\\写给程序员的Python教程\\pyfund\\palindrome\\palindrome_env\\Lib\\site-packages\\palindrome-1.0-py3.11.egg\\palindrome.py'

        在这里,使用模块的__file__属性来查看模块从哪里导入,可以看到正在从虚拟环境的sete-packages导入模块。

        退出Python REPL之后,不要忘记切换回源代码目录:

(palindrome_env) d:\>cd \python\写给程序员的Python教程\pyfund\palindrome

(palindrome_env) d:\python\写给程序员的Python教程\pyfund\palindrome>

B.3 使用distutils打包

        setup()的另一个有用的功能是它可以创建各种类型的“分发”格式。将指定的所有模块,捆绑到易于分发的软件包中。可以使用sdist命令(这是source distribution的缩写)执行此操作:

(palindrome_env) d:\python\写给程序员的Python教程\pyfund\palindrome>python setup.py sdist --format zip
running sdist
running egg_info
writing palindrome.egg-info\PKG-INFO
writing dependency_links to palindrome.egg-info\dependency_links.txt
writing top-level names to palindrome.egg-info\top_level.txt
reading manifest file 'palindrome.egg-info\SOURCES.txt'
writing manifest file 'palindrome.egg-info\SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md

running check
creating palindrome-1.0
creating palindrome-1.0\palindrome.egg-info
copying files to palindrome-1.0...
copying palindrome.py -> palindrome-1.0
copying setup.py -> palindrome-1.0
copying palindrome.egg-info\PKG-INFO -> palindrome-1.0\palindrome.egg-info
copying palindrome.egg-info\SOURCES.txt -> palindrome-1.0\palindrome.egg-info
copying palindrome.egg-info\dependency_links.txt -> palindrome-1.0\palindrome.egg-info
copying palindrome.egg-info\top_level.txt -> palindrome-1.0\palindrome.egg-info
Writing palindrome-1.0\setup.cfg
creating 'dist\palindrome-1.0.zip' and adding 'palindrome-1.0' to it
adding 'palindrome-1.0'
adding 'palindrome-1.0\palindrome.egg-info'
adding 'palindrome-1.0\palindrome.py'
adding 'palindrome-1.0\PKG-INFO'
adding 'palindrome-1.0\setup.cfg'
adding 'palindrome-1.0\setup.py'
adding 'palindrome-1.0\palindrome.egg-info\dependency_links.txt'
adding 'palindrome-1.0\palindrome.egg-info\PKG-INFO'
adding 'palindrome-1.0\palindrome.egg-info\SOURCES.txt'
adding 'palindrome-1.0\palindrome.egg-info\top_level.txt'
removing 'palindrome-1.0' (and everything under it)

         在目录dist创建了新生成的分发文件:

(palindrome_env) d:\python\写给程序员的Python教程\pyfund\palindrome>dir dist
 驱动器 D 中的卷没有标签。


 d:\python\写给程序员的Python教程\pyfund\palindrome\dist 的目录

2023/07/07  10:26    <DIR>          .
2023/07/07  10:26    <DIR>          ..
2023/07/07  09:17             3,370 palindrome-1.0-py3.11.egg
2023/07/07  10:26             2,779 palindrome-1.0.zip
               2 个文件          6,149 字节

        这个palindrome-1.0.zip文件中打包了项目的源码以及setup.py脚本。可以把这个zip文件发送给使用人,他们可以使用setup.py将代码安装到他们自己的系统中。

        sdist命令可以生成各种类型的分发。使用--help-formats选项可以查看。

(palindrome_env) d:\python\写给程序员的Python教程\pyfund\palindrome>python setup.py sdist --help-formats
List of available source distribution formats:
  --formats=bztar  bzip2'ed tar-file
  --formats=gztar  gzip'ed tar-file
  --formats=tar    uncompressed tar file
  --formats=xztar  xz'ed tar-file
  --formats=zip    ZIP file
  --formats=ztar   compressed tar file

        这一节只是涉及distutils的基础知识,可以通过传递--help到setup.py来找到更多有关如何使用distutils的信息:

(palindrome_env) d:\python\写给程序员的Python教程\pyfund\palindrome>python setup.py --help
Common commands: (see '--help-commands' for more)

  setup.py build      will build the package underneath 'build/'
  setup.py install    will install the package

Global options:
  --verbose (-v)      run verbosely (default)
  --quiet (-q)        run quietly (turns verbosity off)
  --dry-run (-n)      don't actually do anything
  --help (-h)         show detailed help message
  --no-user-cfg       ignore pydistutils.cfg in your home directory
  --command-packages  list of packages that provide distutils commands

Information display options (just display information, ignore any commands)
  --help-commands     list all available commands
  --name              print package name
  --version (-V)      print package version
  --fullname          print <package name>-<version>
  --author            print the author's name
  --author-email      print the author's email address
  --maintainer        print the maintainer's name
  --maintainer-email  print the maintainer's email address
  --contact           print the maintainer's name if known, else the author's
  --contact-email     print the maintainer's email address if known, else the
                      author's
  --url               print the URL for this package
  --license           print the license of the package
  --licence           alias for --license
  --description       print the package description
  --long-description  print the long package description
  --platforms         print the list of platforms
  --classifiers       print the list of classifiers
  --keywords          print the list of keywords
  --provides          print the list of packages/modules provided
  --requires          print the list of packages/modules required
  --obsoletes         print the list of packages/modules made obsolete

usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
   or: setup.py --help [cmd1 cmd2 ...]
   or: setup.py --help-commands
   or: setup.py cmd --help

        对于很多简单的项目,你会发现本节知识已经涵盖了几乎所有你需要知道的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值