首頁  >  文章  >  後端開發  >  Python 函式庫:編寫、打包和分發的綜合指南

Python 函式庫:編寫、打包和分發的綜合指南

WBOY
WBOY原創
2023-09-03 17:37:011031瀏覽

Python 是一種出色的程式語言,但打包是其最弱點之一。這是社會上眾所周知的事實。多年來,安裝、導入、使用和創建套件的過程已經有了很大改進,但它仍然無法與 Go 和 Rust 等較新的語言相提並論,後者從 Python 和其他成熟語言的鬥爭中學到了很多東西。

在本教程中,您將學習有關編寫、打包和分發您自己的套件所需的所有知識。

如何寫 Python 函式庫

Python 函式庫是組織為 Python 套件的 Python 模組的連貫集合。一般來說,這意味著所有模組都位於同一目錄下,並且該目錄位於 Python 搜尋路徑上。

讓我們快速寫一個小小的 Python 3 套件並說明所有這些概念。

病理套件

Python 3 有一個優秀的 Path 對象,這相對於 Python 2 笨拙的 os.path 模組來說是一個巨大的改進。但它缺少一項關鍵功能——尋找當前腳本的路徑。當您想要定位相對於目前腳本的存取檔案時,這一點非常重要。

很多情況下,腳本可以安裝在任何位置,因此不能使用絕對路徑,而工作目錄可以設定為任何值,因此不能使用相對路徑。如果要存取子目錄或父目錄中的文件,則必須能夠找出目前腳本目錄。

以下是在 Python 中執行此操作的方法:

import pathlib

script_dir = pathlib.Path(__file__).parent.resolve()

要存取目前腳本目錄的「data」子目錄中名為「file.txt」的文件,可以使用以下程式碼: print(open(str(script_dir/' data/file.txt'). read())

使用病理學包,您有一個內建的 script_dir 方法,您可以像這樣使用它:

from pathology.Path import script_dir

print(open(str(script_dir()/'data/file.txt').read())

是的,有點拗口。病理包非常簡單。它從 pathlib 的 Path 派生出自己的 Path 類,並添加一個始終返回調用腳本的路徑的靜態 script_dir()

這裡是實作:

import pathlib
import inspect

class Path(type(pathlib.Path())):
    @staticmethod
    def script_dir():
        print(inspect.stack()[1].filename)
        p = pathlib.Path(inspect.stack()[1].filename)
        return p.parent.resolve()

由於pathlib.Path的跨平台實現,您可以直接從它派生,並且必須從特定子類別派生(PosixPath or WindowsPath)。 script_dir 解析使用檢查模組來尋找呼叫者及其檔案名稱屬性。

測試病理套件

每當您編寫的內容不僅僅是一次性腳本時,您就應該對其進行測試。病理學模組也不例外。以下是使用標準單元測試框架的測試:

import os
import shutil 
from unittest import TestCase
from pathology.path import Path


class PathTest(TestCase):
    def test_script_dir(self):
        expected = os.path.abspath(os.path.dirname(__file__))
        actual = str(Path.script_dir())
        self.assertEqual(expected, actual)

    def test_file_access(self):
        script_dir = os.path.abspath(os.path.dirname(__file__))
        subdir = os.path.join(script_dir, 'test_data')
        if Path(subdir).is_dir():
            shutil.rmtree(subdir)
        os.makedirs(subdir)
        file_path = str(Path(subdir)/'file.txt')
        content = '123'
        open(file_path, 'w').write(content)
        test_path = Path.script_dir()/subdir/'file.txt'
        actual = open(str(test_path)).read()

        self.assertEqual(content, actual)

Python 路徑

Python 套件必須安裝在 Python 搜尋路徑上的某個位置,才能由 Python 模組匯入。 Python 搜尋路徑是目錄列表,並且始終在 sys.path 中可用。這是我目前的 sys.path:

>>> print('\n'.join(sys.path))

/Users/gigi.sayfan/miniconda3/envs/py3/lib/python36.zip
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/lib-dynload
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/site-packages
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg 

請注意,輸出的第一個空白行代表目前目錄,因此您可以從目前工作目錄匯入模組,無論它是什麼。您可以直接向 sys.path 新增或刪除目錄。

您也可以定義一個 PYTHONPATH 環境變量,還有一些其他方法可以控制它。預設包含標準 site-packages,這是您透過 pip go 安裝軟體套件的位置。

如何打包 Python 函式庫

現在我們有了程式碼和測試,讓我們將其全部打包到適當的庫中。 Python 透過 setup 模組提供了一個簡單的方法。您在程式包的根目錄中建立一個名為 setup.py 的檔案。

setup.py 檔案包含大量元資料信息,例如作者、許可證、維護者以及有關套件的其他資訊。這是對 packages 項目的補充,該項目使用從 setuptools 導入的 find_packages() 函數來尋找子包。

這是病理包的setup.py檔:

from setuptools import setup, find_packages

setup(name='pathology',
      version='0.1',
      url='https://github.com/the-gigi/pathology',
      license='MIT',
      author='Gigi Sayfan',
      author_email='the.gigi@gmail.com',
      description='Add static script_dir() method to Path',
      packages=find_packages(exclude=['tests']),
      long_description=open('README.md').read(),
      zip_safe=False)

來源分發包

來源分發套件是指包含 Python 套件、模組和用於套件發布的其他檔案(例如版本 1、版本 2 等)的存檔檔案。文件分發後,最終用戶可以下載並將其安裝在他們的作業系統上。

要建立來源分發包 (sdist),請執行: python setup.py sdist

讓我們建立一個原始碼發行版:

$ python setup.py sdist
running sdist
running egg_info
creating pathology.egg-info
writing pathology.egg-info/PKG-INFO
writing dependency_links to pathology.egg-info/dependency_links.txt
writing top-level names to pathology.egg-info/top_level.txt
writing manifest file 'pathology.egg-info/SOURCES.txt'
reading manifest file 'pathology.egg-info/SOURCES.txt'
writing manifest file 'pathology.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt

running check
creating pathology-0.1
creating pathology-0.1/pathology
creating pathology-0.1/pathology.egg-info
copying files to pathology-0.1...
copying setup.py -> pathology-0.1
copying pathology/__init__.py -> pathology-0.1/pathology
copying pathology/path.py -> pathology-0.1/pathology
copying pathology.egg-info/PKG-INFO -> pathology-0.1/pathology.egg-info
copying pathology.egg-info/SOURCES.txt -> pathology-0.1/pathology.egg-info
copying pathology.egg-info/dependency_links.txt -> pathology-0.1/pathology.egg-info
copying pathology.egg-info/not-zip-safe -> pathology-0.1/pathology.egg-info
copying pathology.egg-info/top_level.txt -> pathology-0.1/pathology.egg-info
Writing pathology-0.1/setup.cfg
creating dist
Creating tar archive
removing 'pathology-0.1' (and everything under it)

該警告是因為我使用了非標準的 README.md 檔案。忽略它是安全的。上面的命令將為目前作業系統建立一個預設格式的存檔檔案。對於Unix系統,將在dist目錄下產生一個gzipped tar檔案:

$ ls -la dist
total 8
drwxr-xr-x   3 gigi.sayfan  gigi.sayfan   102 Apr 18 21:20 .
drwxr-xr-x  12 gigi.sayfan  gigi.sayfan   408 Apr 18 21:20 ..
-rw-r--r--   1 gigi.sayfan  gigi.sayfan  1223 Apr 18 21:20 pathology-0.1.tar.gz

如果您使用的是 Windows,則會產生一個 zip 檔案。

您也可以使用格式選項指定其他附加文件格式,如下所示。

python setup.py sdist --formats=gztar,zip

例如,上述命令将生成一个 gzip 压缩的 tarball 和一个 zip 文件。

可用的不同格式有:

  • zip: .zip
  • gztar: .tar.gz
  • bztar: .tar.bz2
  • xztar: .tar.xz
  • ztar: .tar.Z
  • tar: .tar

二进制分发

要创建一个名为“wheel”的二进制发行版,请运行: python setup.py bdist_wheel

这是一个二进制发行版:

$ python setup.py bdist_wheel
running bdist_wheel
running build
running build_py
creating build
creating build/lib
creating build/lib/pathology
copying pathology/__init__.py -> build/lib/pathology
copying pathology/path.py -> build/lib/pathology
installing to build/bdist.macosx-10.7-x86_64/wheel
running install
running install_lib
creating build/bdist.macosx-10.7-x86_64
creating build/bdist.macosx-10.7-x86_64/wheel
creating build/bdist.macosx-10.7-x86_64/wheel/pathology
copying build/lib/pathology/__init__.py -> build/bdist.macosx-10.7-x86_64/wheel/pathology
copying build/lib/pathology/path.py -> build/bdist.macosx-10.7-x86_64/wheel/pathology
running install_egg_info
running egg_info
writing pathology.egg-info/PKG-INFO
writing dependency_links to pathology.egg-info/dependency_links.txt
writing top-level names to pathology.egg-info/top_level.txt
reading manifest file 'pathology.egg-info/SOURCES.txt'
writing manifest file 'pathology.egg-info/SOURCES.txt'
Copying pathology.egg-info to build/bdist.macosx-10.7-x86_64/wheel/pathology-0.1-py3.6.egg-info
running install_scripts
creating build/bdist.macosx-10.7-x86_64/wheel/pathology-0.1.dist-info/WHEEL

病理包仅包含纯Python模块,因此可以构建通用包。如果您的软件包包含 C 扩展,则必须为每个平台构建单独的轮子:

$ ls -la dist
total 16
drwxr-xr-x   4 gigi.sayfan  gigi.sayfan   136 Apr 18 21:24 .
drwxr-xr-x  13 gigi.sayfan  gigi.sayfan   442 Apr 18 21:24 ..
-rw-r--r--   1 gigi.sayfan  gigi.sayfan  2695 Apr 18 21:24 pathology-0.1-py3-none-any.whl
-rw-r--r--   1 gigi.sayfan  gigi.sayfan  1223 Apr 18 21:20 pathology-0.1.tar.gz

要更深入地了解打包 Python 库的主题,请查看如何编写您自己的 Python 包。

如何分发 Python 包

Python 有一个名为 PyPI(Python 包索引)的中央包存储库。 PyPI 可以轻松管理不同版本的包。例如,如果用户需要安装特定的软件包版本,pip 知道在哪里查找它。

当您使用 pip 安装 Python 包时,它将从 PyPI 下载该包(除非您指定不同的存储库)。为了分发我们的病理包,我们需要将其上传到 PyPI 并提供 PyPI 所需的一些额外元数据。步骤是:

  • 升级您的 pip 版本。
  • 在 PyPI 上创建一个帐户(只需一次)。
  • 注册您的包裹。
  • 上传您的包。

升级您的 pip 版本

确保您的操作系统中安装了最新版本的 pip。要升级 pip,请发出以下命令

python3 -m pip install --upgrade pip

创建帐户

您可以在 PyPI 网站上创建帐户。然后在您的主目录中创建一个 .pypirc 文件:

[distutils] 
index-servers=pypi
 
[pypi]
repository = https://pypi.python.org/pypi
username = the_gigi

出于测试目的,您可以将 pypitest 索引服务器添加到您的 .pypirc 文件中:

[distutils]
index-servers=
    pypi
    pypitest

[pypitest]
repository = https://testpypi.python.org/pypi
username = the_gigi

[pypi]
repository = https://pypi.python.org/pypi
username = the_gigi

注册您的包裹

如果这是您的软件包的第一个版本,您需要使用 PyPI 注册它。使用setup.py的注册命令。它会询问您的密码。请注意,我将其指向此处的测试存储库:

$ python setup.py register -r pypitest
running register
running egg_info
writing pathology.egg-info/PKG-INFO
writing dependency_links to pathology.egg-info/dependency_links.txt
writing top-level names to pathology.egg-info/top_level.txt
reading manifest file 'pathology.egg-info/SOURCES.txt'
writing manifest file 'pathology.egg-info/SOURCES.txt'
running check
Password:
Registering pathology to https://testpypi.python.org/pypi
Server response (200): OK

上传您的包

现在包已注册,我们可以上传它了。我建议使用麻线,这样更安全。像往常一样使用 pip install twine 安装它。然后使用 twine 上传您的包并提供您的密码(在下面进行编辑):

$ twine upload -r pypitest -p <redacted> dist/*
Uploading distributions to https://testpypi.python.org/pypi
Uploading pathology-0.1-py3-none-any.whl
[================================] 5679/5679 - 00:00:02
Uploading pathology-0.1.tar.gz
[================================] 4185/4185 - 00:00:01 

该软件包现已在 PyPI 官方网站上提供,如下所示。

Python 库:编写、打包和分发的综合指南

要使用 pip 安装它,只需发出以下命令:

pip install pathology

要更深入地了解分发包的主题,请查看如何共享您的 Python 包。

结论

在本教程中,我们完成了编写 Python 库、打包并通过 PyPI 分发它的完整过程。此时,您应该拥有编写库并与世界共享库的所有工具。

本文已根据 Esther Vaati 的贡献进行了更新。 Esther 是 Envato Tuts+ 的软件开发人员和作家。

以上是Python 函式庫:編寫、打包和分發的綜合指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn