• 一文搞懂如何自己写一个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

  • 相关阅读:
    计算螺栓点云的高度【halcon三维计算】
    景联文科技:深度了解语音识别之发音词典及语音数据采集标注
    基于jacoco和CI做代码覆盖率检测
    ThreadPoolExecutor构造函数重要参数分析,以及创建线程池
    checkbox 设置默认值
    echarts label fomatter a b c d含义
    git报错The project you were looking for could not be found 解决方式
    牛客每日刷题
    Codeforces Round #814 (Div. 2)
    【实验1:RT-Thread环境搭建+IIC光线传感器实验】
  • 原文地址:https://www.cnblogs.com/meet/p/18057112