写点什么

提高代码可重用性, 减少重复劳动 --Python 自定义模块并上传到 pypi, 把自己轮子供别安装使用

作者:迷彩
  • 2022 年 8 月 10 日
    广东
  • 本文字数:3263 字

    阅读完需:约 11 分钟

前言

我们都知道程序中可通过定义函数来减少工作量,提高代码的可重用性,从而提高我们的开发效率.我们一直 import 的是别人的模块,那如果我们需要使用自己的模块,或者开发一个自己的模块供别人使用,我们自己造轮子该怎么做呢?

我们实际的开发中,只在一个文件中编写代码是不太可能的,当开发大型项目的时候,一个文件过于臃肿,第一个是不利于阅读,代码可读性极差,还不利于团队协作开,所以这时候我们需要引入模块的概念.下面我们来了解什么是模块


什么是模块


我们对模块并不陌生,可能你已经使用多次,我们在使用 import 的时候就是使用到模块,比如我们在使用数组的时候会 import numpy,我们在操作 Excel 数据时会 import pandas.其实我们之前所有自己编写的代码片段都可以修改为一个模块,避免重复的劳动,提高开发的灵活性,接下来我们看下 numpy 包含的内容


我们可以使用一下代码输出 numpy 模块中定义的全部内容的名称.

import numpyprint(dir(numpy))
复制代码

运行结果部分截图:从截图中可以看出里面包含了很多我们常用的函数


下图的代码就是我们经常使用的 numpy 模块中的 Arrayterator 大数组的缓冲迭代器的源码:


接着我们详细分析 import numpy 是如何在程序中起作用的,当程序运行到 import numpy 的时候,便会开始寻找 copy 模块,这一句就是告诉 Python 我们在程序中要使用该模块的内容.我们在使用之前已经使用 pip install numpy 安装过,已经把 numpy 安装到本地对应版本的 Python 中,在代码中我们无需指明模块目录,Python 知道他的具体位置.

除了 import,还有一条我们常用的引用的语句:from...import,他是将模块部分内容引到我们的程序中.比如下面这段代码:

from math import sqrtprint("根号100:", sqrt(100))
复制代码

程序将根号函数 sqrt 从 math 模块中引入程序并使用他,这种引入方式不必使用模块模块名加点符(比如:copy.deepcopy(data))。可以直接使用函数名,但是这也带来了名称冲突问题.这样只会引入模块的部分内容,减少了计算机的工作量,但是,一般来说我们在程序中应该尽量避免使用 from...import 语句,因为这条语句可能会导致程序中出现名称冲突并且让我们的程序更难被别人理解。


自定义模块

通过上述的讲解,大家对模块可能还是感觉有点神秘,如果你之前已经写过的案例或是练习的程序,那么在无形中你已经定义了很多模块。每一个独立的 Python 程序都可以当成一个模块。接下来我们使用代码段的方式正式创建一个模块并调用他。

也许大家学习其他编程语言的时候或者在数学中了解过斐波那契数列,甚至还使用其他语言实现过,这次咱们也使用 Fibonacci 数列练练手。以此为例创建一个自定义模块.文件名:myfirstmodule.py

def fibo(n):    if n<=1:        return n    else:        return (fibo(n-1)+fibo(n-2))        def printFibo(n):    for i in range(n):        print(fibo(n))                __version__ = '0.1'
复制代码

代码中创建了两个函数,一个是实现斐波那契数列,另外一个 printFibo(n)函数是控制输出数列个数的循环代码装入,最后添加了一行表示模块当前的版本号的变量,让该文件的内容更像一个模块。


接下来在模块文件 myfirstmodule.py 同目录下创建调用模块文件 callModule.py,其内容如下:

import myfirstmodule
print('使用的模块版本:', myfirstmodule.__version__)myfirstmodule.printFibo(20)
复制代码

运行结果如下:

调用的程序中,我们使用模块名加点调用模块中的变量和函数。那么我们 Python 是如何找到我们定义的模块呢?在创建 callModule.py 文件时我们提到过要在同目录下创建,这是因为当导入模块时 Python 会按照:"当前目录"->PYTHONPATH(就是安装 Python 的默认路径)下的每一个目录->默认路径(系统中的默认路径)这个顺序搜索模块直到找到该模块.


上传到 pypi

准备

注册 PyPI 用户

Pypi 是什么

pypi 是一个 python 包的仓库,里面有很多别人写好的 python 库,你可以通过 easy_install 或者 pip 进行安装,方便用户更方面的使用你的代码模块。所以我们平时使用 pip install 这个命令安装的模块都是从这里拉取的

注册完 pypi 需要验证邮箱!

代码上传到 pypi 的流程

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

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

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

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

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

Copyright (c) 2018 The Python Packaging Authority
Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE.
复制代码

README 文件使用过 github 的童鞋都不陌生,其实就是项目介绍和使用说明

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

3、进行打包代码并上传到 pypi

为了保证效果,在打包之前我们可以验证 setup.py 的正确性,打开命令行工具,然后定位到你的项目目录,比如我的是 mymd;接着执行下面的代码

    python setup.py check

3.1、写好的代码先上传到 GitHub:

3.2、生成 whl 文件并上传给 PYPI

进入你 python 环境,打开终端,进入到 mymd 文件夹下。我 python 环境是 conda 环境,默认名称 base

conda activate basepip install setuptools  -i https://mirrors.aliyun.com/pypi/simple/pip install wheel -i https://mirrors.aliyun.com/pypi/simple/
复制代码

3.3 使用python setup.py sdist bdist_wheel命令进行打包,执行完成后会在 mymd 文件夹生成 build、dist、xiaomicaiFibo_pip_fibo.egg-info 三个文件夹




4、上传到 pypi

使用 twine 上传代码,如果没有安装过 twine 需要先使用一下代码安装,安装命令如下:

pip install twine -i https://mirrors.aliyun.com/pypi/simple/

上传:twine upload --repository-url https://upload.pypi.org/legacy/ dist/*

执行这条命令输入用户名和密码,用户名密码是你注册 PIPY 时的用户名密码

上传成功如下图:


这时候进入 pypi 后台就可以看到自己上传的项目:

安装并测试我们的上传的模块

安装我们自己的模块:

pip install xiaomicaiFibo-pip-fibo
复制代码



测试代码运行:

from xiaomicaiFibo import myfirstmodule
print('使用的模块版本:', myfirstmodule.__version__)myfirstmodule.printFibo(20)
复制代码

运行结果:

至此,我们已经已经完成了一次自定义模块以及把自己定义的模块上传到 Pypi 供别人使用的完整流程。光说不练假把戏,光看不做只是眼睛学会了,手没学会,动手实践起来吧~把自己的模块分享出来让大家开发变得更加简单!

发布于: 刚刚阅读数: 5
用户头像

迷彩

关注

我的工作是常年写bug|公众号:编程架构之美 2020.06.18 加入

修bug的菜鸟~公众号:“互联网有啥事”已改名为“编程架构之美”

评论

发布
暂无评论
提高代码可重用性,减少重复劳动--Python自定义模块并上传到pypi,把自己轮子供别安装使用_Python_迷彩_InfoQ写作社区