博客 / 詳情

返回

一文搞懂如何自己寫一個Python庫

一文搞懂如何自己寫一個Python庫

你是否曾想過為自己的Python項目編寫一個庫,以便在不同項目中重複使用代碼?

並且能在PyPI倉庫中發佈,並通過pip install 庫名來安裝使用

1.png

編寫Python庫可能看起來有些複雜,但實際上並非如此。本文將為你提供一份簡明的指南,帶你逐步瞭解如何編寫自己的Python庫。

文章共分以下部分:

  1. 準備工作
  2. 創建項目
  3. 編寫代碼
  4. 添加庫的文檔和註釋
  5. 測試你的庫
  6. 發佈到PyPI測試倉庫
  7. 發佈到PyPI官方倉庫
  8. 通過pip安裝測試使用
  9. 總結

一、準備工作

1.1 註冊PyPI賬號

  • https://test.pypi.org/平台上自己註冊一個賬號,用於測試發佈的庫
  • https://pypi.org/平台上自己註冊一個賬號,用於正式發佈庫

1.2 為你的庫取個好聽的名字

在開始編寫之前,你需要明確你的庫將要實現的功能以及它的使用場景。併為你的庫取一個好聽好記的名字,這有助於確保你的庫能夠滿足用户的需求,並且避免在後期頻繁修改。

例如:我想實現一個自己常用庫的封裝,取名為yourtools , 為什麼不直接取tools呢?因為有重名的庫,所以大家取名的時候記得先去PyPI平台上搜索看看有沒有重名的庫。重名的話無法發佈~

二、創建項目

準備工作完成後,接下來開始創建一個新的目錄來作為你的庫的項目文件夾。在這個目錄中,你需要包含一個setup.py文件來描述你的庫,並且在適當的位置創建Python模塊文件以及其他必要的文件。

├── yourtools              目錄
│   └── db                 目錄
│       ├── __init__.py
│       └── mysql.py     工具類
├── requirements.txt     依賴庫
├── setup.py             安裝腳本
├── README.md          説明文檔
├── upload_pypi.sh       上傳到官方PyPI倉庫腳本
├── upload_pypi_test.sh 上傳到官方測試PyPI倉庫腳本

這裏我新建了以上文件目錄,並對每個文件進行了解釋。以上文件都空着即可,後續會詳細講解每個文件的代碼

三、編寫代碼

開始編寫你的Python代碼,實現你所定義的功能。確保你的代碼結構清晰,遵循Python的最佳實踐和PEP規範。

本次演示我們將實現一個針對pymysql通用的MySQL工具類

mysql.py

import pymysql
from sshtunnel import SSHTunnelForwarder
from .dbutils import DBConfig


class MySQL:
    def __init__(self, db_config, ssh_tunnel=None):
        self.dbconfig = DBConfig(db_config)
        if ssh_tunnel:
            ssh_tunnel.start()
            self.dbconfig.host = ssh_tunnel.local_bind_host
            self.dbconfig.port = ssh_tunnel.local_bind_port
        self._init()

    def _init(self):
        try:
            self.connect = pymysql.connect(
                host=str(self.dbconfig.host),
                port=self.dbconfig.port,
                user=str(self.dbconfig.username),
                passwd=str(self.dbconfig.password),
                db=str(self.dbconfig.db),
                charset=str(self.dbconfig.charset)
            )
            self.cursor = self.connect.cursor()
            return True
        except Exception as err:
            raise Exception("MySQL Connection error", err)
            return False

    def get_conn(self):
        if self.connect:
            return self.connect
        else:
            self._init()
            return self.connect

    def close_conn(self):
        if self.connect:
            self.connect.close()

    def query(self, sql, param=None):
        """
        Query data
        :param sql:
        :param param:
        :param size: Number of rows of data you want to return
        :return:
        """
        cur = self.connect.cursor(cursor=pymysql.cursors.DictCursor)
        rows = None
        try:
            cur.execute(sql, param)
            rows = cur.fetchall()
        except Exception as e:
            raise Exception(e)
            self.connect.rollback()
        cur.close()
        return rows

    def execute(self, sql):
        """
        exec DML:INSERT、UPDATE、DELETE
        :param sql: dml sql
        :param param: string|list
        :return: Number of rows affected
        """
        try:
            self.cursor.execute(sql)
            self.connect.commit()
        except Exception as e:
            self.connect.rollback()

代碼很簡單,這裏不再解釋。

為了後續import方便,我們在__init__.py裏對外部暴露的包名規範一下

# __init__.py
from .db.mysql import MySQL

四、添加庫的文檔和註釋

良好的文檔和註釋對於一個庫的成功至關重要。為你的代碼添加詳細的文檔字符串和註釋,以便其他人能夠理解你的代碼,並且能夠方便地使用你的庫。

接下來,我們編寫README.md,這個README.md文件內容決定了你的庫在PyPI平台展示的內容,例如:

readme.png

五、測試你的庫

庫發佈之前要進行自測,避免pip安裝使用時有問題。可以直接在pycharm裏測試使用,也可以外部調用測試,這裏我們假設我們mysql.py代碼已經完成沒問題。

六、發佈到PyPI測試環境

一旦你確認你的庫已經完善,你可以選擇將其發佈到PyPI等Python包管理器中,使其他人能夠方便地安裝和使用你的庫。

編寫發佈庫setup.py文件

import setuptools
import re
import requests
from bs4 import BeautifulSoup

package_name = "yourtools"


def curr_version():
    # 方法1:通過文件臨時存儲版本號
    # with open('VERSION') as f:
    #     version_str = f.read()

    # 方法2:從官網獲取版本號
    url = f"https://pypi.org/project/{package_name}/"
    response = requests.get(url)
    soup = BeautifulSoup(response.content, "html.parser")
    latest_version = soup.select_one(".release__version").text.strip()
    return str(latest_version)


def get_version():
    # 從版本號字符串中提取三個數字並將它們轉換為整數類型
    match = re.search(r"(\d+)\.(\d+)\.(\d+)", curr_version())
    major = int(match.group(1))
    minor = int(match.group(2))
    patch = int(match.group(3))

    # 對三個數字進行加一操作
    patch += 1
    if patch > 9:
        patch = 0
        minor += 1
        if minor > 9:
            minor = 0
            major += 1
    new_version_str = f"{major}.{minor}.{patch}"
    return new_version_str


def upload():
    with open("README.md", "r") as fh:
        long_description = fh.read()
    with open('requirements.txt') as f:
        required = f.read().splitlines()

    setuptools.setup(
        name=package_name,
        version=get_version(),
        author="Author's name",  # 作者名稱
        author_email="xxxxxxx@163.com", # 作者郵箱
        description="Python helper tools", # 庫描述
        long_description=long_description,
        long_description_content_type="text/markdown",
        url="https://pypi.org/project/yourtools/", # 庫的官方地址
        packages=setuptools.find_packages(),
        data_files=["requirements.txt"], # yourtools庫依賴的其他庫
        classifiers=[
            "Programming Language :: Python :: 3",
            "License :: OSI Approved :: MIT License",
            "Operating System :: OS Independent",
        ],
        python_requires='>=3.6',
        install_requires=required,
    )


def write_now_version():
    print("Current VERSION:", get_version())
    with open("VERSION", "w") as version_f:
        version_f.write(get_version())


def main():
    try:
        upload()
        print("Upload success , Current VERSION:", curr_version())
    except Exception as e:
        raise Exception("Upload package error", e)


if __name__ == '__main__':
    main()

upload_pypi_test.sh

為了保證庫使用正常,我們建議先把庫發佈到PyPI的測試環境:https://test.pypi.org,我們可以直接修改upload_pypi_test.sh

#!/bin/zsh

rm -rf ./build
rm -rf ./dist
rm -rf ./yourtools.egg-info

python3 setup.py sdist bdist_wheel

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

upload_pypi_test.sh代碼編寫完後,可以執行sh upload_pypi_test.sh發佈到測試環境,發佈過程中,需要輸入PyPI平台的用户名和密碼

pypi_test.png

發佈到測試環境後,可以直接通過pip命令安裝pip install -i https://test.pypi.org/simple/yourtools

如果pip安裝成功後,可以寫一個test.py文件來測試使用,由於我們在__init__.py裏提前import了MySQL,所以這裏我們只需要執行如下命令即可導入

from yourtools import MySQL

如果以上命令沒報錯,則説明庫導入完成,下面可以測試數據庫工具類的增刪改查功能了

def test_mysql():
    dbconfg = {
        'host': '172.0.0.1',
        'port': 3306,
        'username': 'root',
        'password': '123456',
        'db': 'test',
        'charset': 'utf8'
    }
    server = SSHTunnelForwarder(
        ('跳板機服務器IP', 45535),
        ssh_username='root',
        ssh_password='123456',
        remote_bind_address=('遠程數據庫IP', 3366),
        local_bind_address=('127.0.0.1', 3366)
    )
    # 不使用跳板機
    mysql = MySQL(dbconfg)
    # 使用跳板機,需要傳遞一個SSHTunnelForwarder對象
    mysql = MySQL(dbconfg,ssh_tunnel=server)
    
    # query data
    result = mysql.query("select * from users")
    print(result)
    # dml sql 
    result = mysql.execute("insert into users(name,birthday,ts) values('滅霸2','2022-11-01 16:00:00','2022-11-01 16:00:00') ")

七、發佈到PyPI官方倉庫

如果以上測試沒問題,下面我們將該庫發佈到PyPI的生產倉庫中,同樣邏輯,修改upload_pypi.sh文件

#!/bin/bash

# Upload project to pypi

rm -rf ./build
rm -rf ./dist
rm -rf ./yourtools.egg-info

python3 setup.py sdist bdist_wheel

python3 -m twine upload dist/*

執行sh upload_pypi.sh發佈到PyPI生產環境,發佈過程中,需要輸入PyPI平台的用户名和密碼

八、通過pip安裝測試使用

當以上步驟全部完成後,恭喜你,已經實現了將自己寫的Python發佈到PyPI倉庫中了,接下來就可以把這個牛逼轟轟的庫告訴你身邊的朋友推廣使用了。

pip_install.png

九、總結

  1. 本文基於yourtools庫作為演示説明,該庫地址https://pypi.org/project/yourtools/
  2. yourtools庫源碼:https://github.com/FearlessPeople/yourtools
  3. 小提示:通過setup.py文件,還可以將你的代碼部署到私有Python解釋器環境中喲,例如你公司服務器上的Python環境裏

以上就是編寫Python庫的步驟,通過這些步驟,你也可以輕鬆地編寫出一個Python庫,為自己和其他人提供便利。祝你編寫愉快!

關注公眾號【大喇叭IT】,回覆python 可進羣溝通交流

7.jpeg

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.