模块与包开发¶
1. 第三方模块与包¶
pip ("Pip Installs Packages"的首字母递归缩写)是一个现代的,通用的 Python 包管理工具,它提供了对Python第三方包的查找、下载、安装、卸载等功能。在python2.7以上版本的解释器安装到本地系统以后,pip就被当做内置标准库模块被安装到了解释器中,我们可以把它当做系统命令一样直接在系统终端来使用pip安装、下载、管理第三方模块或包。
pip 官网:https://pypi.org/project/pip/
pypi是pip的官网,同时也是python官方提供给开发者上传和下载第三方模块的官方平台。
可以通过查看pip版本来判断是否已经在当前python解释器中安装了pip
pip --version # Python2.x 版本命令
pip3 --version # Python3.x 版本命令[如果当前系统只安装了python3版本解释器,也可以直接使用pip命令,而不需要加上3]
1.1 基本使用¶
1.2 常用命令¶
| 命令 | 描述 |
|---|---|
| pip --version pip -V |
显示版本和路径 |
| pip --help pip pip -h |
获取帮助 |
| pip install <包名> # 最新版本 pip install <包名> == 1.0.4 # 指定版本 pip install <包名> >= 1.0.4 # 最小版本 |
安装包,自动下载到 Python的Lib/ite-packages目录下 |
| pip uninstall <包名> | 卸载包 |
| pip list | 列出已安装的包 |
| pip list -o | 查看可升级的包 |
| pip freeze > requirements.txt | 导出当前python解释器中已经安装的包列表,并存储到文件中 |
| pip download <包名> -d "要保存的文件路径" | 下载备份包到本地 |
| pip install -r requirements.txt | 批量安装包,requirements.txt文件 |
| pip install --upgrade <包名> pip install -U <包名> |
升级包 升级指定的包,通过使用==, >=, <=, >, < 来指定一个版本号。 |
| pip search <包名/部分包名> | 搜索包 |
| pip show | 显示安装包信息 |
| pip show -f <包名> | 查看指定包的详细信息 |
| pip install --upgrade pip # python2.x pip3 install --upgrade pip # python3.x |
升级 pip |
由于众所周知的原因,若使用 pip 出现 “connection timeout”错误,这表示连接超时了,此时可以使用国内的镜像网站下载:
清华:https://pypi.tuna.tsinghua.edu.cn/simple/
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣:http://pypi.douban.com/simple/
1.3 psutil¶
文档:https://psutil.readthedocs.io/en/latest/
psutil是一个开源切跨平台的系统信息操作模块,支持Linux、windows等大部分操作系统,是系统管理员和运维人员不可或缺的必备模块。其提供了便利的函数用来获取才做系统的信息,比如CPU,内存,磁盘,网络等。此外,psutil还可以用来进行进程管理,包括判断进程是否存在、获取进程列表、获取进程详细信息等。而且psutil还提供了许多命令行工具提供的功能,包括:ps,top,lsof,netstat,ifconfig, who,df,kill,free,nice,ionice,iostat,iotop,uptime,pidof,tty,taskset,pmap。
根据函数的功能,主要分为CPU、磁盘、内存、网络等几类。
| 函数 | 描述 |
|---|---|
| cpu_count(,[logical]) | 获取CPU的个数,默认获取逻辑CPU个数,当logical=False时,获取物理CPU的个数。 |
| cpu_times(,[percpu]) | 获取系统CPU时间信息,percpu=True表示获取每个CPU的时间信息 |
| cputimespercent(,[percpu]) | 功能和cpu_times大致相同,返回耗时比例。 |
| cpu_percent(,[percpu],[interval]) | 读取CPU的利用率,percpu=True时显示所有物理核心的利用率,interval!=0时,则阻塞时显示interval执行的时间内的平均利用率 |
| cpu_stats() | 以元组的形式返回CPU的统计信息,包括上下文切换,中断,软中断和系统调用次数。 |
| cpu_freq([percpu]) | 返回cpu频率,percpu=True时,返回单个cpu频率 |
| getloadavg() | 以元组的形式返回最近1、5和15分钟内的平均系统负载。 |
| virtual_memory() | 获取系统内存的使用情况 |
| swap_memory() | 获取系统交换内存的统计信息 |
| disk_partitions() | 获取磁盘的分区数据 |
| disk_usage(path) | 获取指定路径所属的分区磁盘的使用统计信息 |
| diskiocounters() | 获取磁盘io操作相关信息 |
| netiocounters(pernic=False, nowrap=True) | 获取网络 I/O 统计信息 |
| net_connections(kind='inet') | 网卡的连接信息 |
| netifaddrs() | 网卡的地址信息 |
| netifstats() | 网卡的状态信息 |
| boot_time() | 系统启动时间 |
| users() | 当前连接到操作系统的用户列表 |
代码:
import psutil
"""查看cpu个数"""
# print( psutil.cpu_count() ) # 4,逻辑CPU个数
# print( psutil.cpu_count(logical=False) ) # 2,物理CPU个数
"""查看cpu运行状态信息"""
# print( psutil.cpu_times(percpu=True) )
# scputimes(
# user=937.05, # 用户进程使用的CPU时间累计
# nice=26.94, # 优先级为负值的进程使用时间
# system=211.48, # 系统内核进程使用时间累计
# idle=1480.49, # CPU空闲时间累计
# iowait=15.02, # 等待IO花费的时间
# irq=0.0, # 硬中断时间累计
# softirq=26.94, # 软中断时间累计
# steal=0.0, # 花费在虚拟机中的时间
# guest=0.0,
# guest_nice=0.0
# )
"""查看cpu运行状态比例信息"""
# print(psutil.cpu_times_percent())
# scputimes(user=0.0, nice=0.0, system=0.0, idle=1.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
"""查看cpu利用率"""
# print( psutil.cpu_percent() ) # 0.0
# print( psutil.cpu_percent(percpu=True) ) # [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
"""CPU的统计信息"""
# print(psutil.cpu_stats())
# scpustats(
# ctx_switches=6672143, # 自操作系统启动的上下文切换次数
# interrupts=4119465, # 自操作系统启动以来的中断数
# soft_interrupts=2539436, # 自操作系统启动以来的软中断数
# syscalls=0 # 自操作系统启动以来的系统调用次数
# )
"""CPU的频率"""
# print(psutil.cpu_freq())
# scpufreq(
# current=2208.0, # 当前频率
# min=0.0, # 最小频率
# max=0.0 # 最大频率
# )
"""以元组的形式返回最近1、5和15分钟内的平均系统负载。"""
# print(psutil.getloadavg()) # (0.48, 0.39, 0.22)
"""获取内存信息"""
# print(psutil.virtual_memory())
# svmem(
# total=5420404736, # 总物理内存
# available=1328689152, # 可用内存
# percent=75.5, # 已用内存的百分比,percent=(total - available) / total * 100
# used=3783630848, # 已用内存
# free=112947200, # 完全未使用的空闲内存
# active=818221056, # 当前正在使用或最近使用的内存
# inactive=3860795392, # 未使用的内存
# buffers=98254848, # 缓冲区内存
# cached=1425571840, # 缓存占用内存
# shared=8818688, # 可以被多个进程同时访问的内存
# slab=289615872 # 缓存内核数据结构的内存
# )
"""以人类可读的方式输出内存大小"""
# from psutil._common import bytes2human
# ret = bytes2human(psutil.virtual_memory()[0])
# print(ret) # 5.0G
"""系统交换内存统计信息"""
# print(psutil.swap_memory())
# sswap(
# total=2147479552, # 总交换内存
# used=284708864, # 已使用的交换内存
# free=1862770688, # 未使用过的空闲交换内存
# percent=13.3, # 已用交换内存的百分比,percent=(total - available) / total * 100
# sin=100696064, # 系统累积从硬盘转入的字节数
# sout=342335488 # 系统累积从硬盘转出的字节数
# )
"""磁盘分区数据"""
# print(psutil.disk_partitions())
# [
# sdiskpart(device='设备路径', mountpoint='挂载点路径', fstype='分区文件系统', opts='以逗号分隔的字符串,指示驱动器/分区的不同挂载选项'),
# sdiskpart(device='/dev/sda5', mountpoint='/', fstype='ext4', opts='rw,relatime,errors=remount-ro'),
# sdiskpart(device='/dev/loop0', mountpoint='/snap/core18/2284', fstype='squashfs', opts='ro,nodev,relatime'),
# sdiskpart(device='/dev/sda1', mountpoint='/boot/efi', fstype='vfat', opts='rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro')
# ]
"""获取指定路径所属的分区磁盘的使用统计信息"""
# print(psutil.disk_usage("/"))
# sdiskusage(
# total=52044496896, # 总磁盘空间
# used=40965885952, # 已用磁盘空间
# free=8404480000, # 用户可用的空间
# percent=83.0 # 用户对磁盘的利用率
# )
"""磁盘io操作相关信息"""
# print(psutil.disk_io_counters())
# sdiskio(
# read_count=130506, # 读取次数
# write_count=74714, # 写入次数
# read_bytes=4225399296, # 读取的字节数
# write_bytes=3102049280, # 写入的字节数
# read_time=52547, # 从磁盘读取所花费的时间(以毫秒为单位)
# write_time=24460, # 写入磁盘所花费的时间(以毫秒为单位)
# read_merged_count=48032, # 合并读取的数量
# write_merged_count=152722, # 合并写入的数量
# busy_time=178944 # 实际 I/O 所花费的时间 (以毫秒为单位)
# )
"""获取网络 I/O 统计信息"""
# print(psutil.net_io_counters())
# snetio(
# bytes_sent=1416706, # 网卡接收的数据字节数
# bytes_recv=14261510, # 网卡接收的数据字节数
# packets_sent=20303, # 网卡发送的数据包数
# packets_recv=27037, # 网卡接收到的数据包数
# errin=0, # 网卡接收数据时的错误总数
# errout=0, # 网卡发送数据时的错误总数
# dropin=0, # 网卡在网络请求被丢弃的传入数据包总数
# dropout=0 # 网卡在网络请求被丢弃的传出数据包总数
# )
"""网卡的连接信息"""
# print(psutil.net_connections())
# [
# sconn(fd=套接字文件描述符(windows和Linux下为-1), family=地址族, type=地址类型, laddr=本地地址, raddr=绝对地址, status=TCP连接的状态, pid=打开套接字的进程的 PID进程ID),
# sconn(fd=-1, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='::', port=22), raddr=(), status='LISTEN', pid=None),
# sconn(fd=-1, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='::', port=22), raddr=(), status='LISTEN', pid=None),
# sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='0.0.0.0', port=22), raddr=(), status='LISTEN', pid=None),
# sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='127.0.0.1', port=6379), raddr=(), status='LISTEN', pid=None),
# sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_DGRAM: 2>, laddr=addr(ip='192.168.233.129', port=68), raddr=addr(ip='192.168.233.254', port=67), status='NONE', pid=None),
# sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='0.0.0.0', port=80), raddr=(), status='LISTEN', pid=None),
# sconn(fd=67, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip='::ffff:127.0.0.1', port=63342), raddr=(), status='LISTEN', pid=3993),
# ]
"""网卡的地址信息"""
# print(psutil.net_if_addrs())
# {
# 'lo': [
# snicaddr(family=地址族, address='主网卡地址', netmask='网络掩码地址', broadcast=广播地址, ptp=点对点接口(通常是 VPN)上的目标地址),
# snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
# snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
# snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)
# ],
# 'ens33': [
# snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.233.129', netmask='255.255.255.0', broadcast='192.168.233.255', ptp=None),
# snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::59eb:3d0b:84e:950f%ens33', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
# snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='00:0c:29:7e:42:9d', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)
# ]
# }
"""网卡的状态信息"""
# print(psutil.net_if_stats())
# # {
# # 'lo': snicstats(isup=表示以太网电缆或 Wi-Fi 已连接, duplex=双工通信类型, speed=网卡速度, mtu=网卡的最大传输单位,以字节表示),
# # 'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536),
# # 'ens33': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1000, mtu=1500)
# # }
"""系统启动时间"""
# print(psutil.boot_time()) # 1650281599.0
"""当前连接到操作系统的用户列表"""
# print(psutil.users())
# [
# 用户类型(name='用户账号名', terminal='终端类型', host='客户端地址', started=创建连接的时间戳, pid=进程ID)
# suser(name='moluo', terminal=':0', host='localhost', started=1650267136.0, pid=2837)
# ]
进程信息管理
import psutil
"""获取当前系统运行的所有进程ID(PID)的排序列表"""
# print(psutil.pids())
# # [1, 2, ... 5509, 5516, 5539]
"""判断指定的pid是否存在"""
# pid_num = psutil.pids()[-10] # psutil.pids()[-10] 仅仅是举例
# result = psutil.pid_exists(pid_num)
"""获取指定pid的进程信息"""
# pid_num = psutil.pids()[-1]
# pid_info=psutil.Process(pid_num)
# print(f"进程名:{pid_info.name()}")
# print(f"进程信息:{pid_info}")
# print(f"启动执行命令:{pid_info.exe()}")
# print(f"进程工作目录:{pid_info.cwd()}")
# print(f"进程执行状态:{pid_info.status()}")
# print(f"进程创建时间:{pid_info.create_time()}")
# print(f"进程uid信息:{pid_info.uids()}")
# print(f"进程gid信息:{pid_info.gids()}")
# print(f"进程的cpu时间信息:{pid_info.cpu_times()}")
# print(f"进程内存利用率:{pid_info.memory_percent()}")
# print(f"进程的IO信息,包括读写IO数字及参数:{pid_info.io_counters()}")
# print(f"进程开启的线程数:{pid_info.num_threads()}")
"""获取当前系统运行的所有进程相关信息"""
# for proc in psutil.process_iter(['pid', 'name', 'username']):
# print(proc.info)
终端执行命令
import psutil
"""psutil.Popen对象,终端执行命令"""
# python3.8 -c 'print("hello world")'
my_process=psutil.Popen(["python3.8","-c",'print("hello world")'])
# 用户程序的信息获取
print("用户进程的名称:{}".format(my_process.name()))
print("用户进程的启动用户:{}".format(my_process.username()))
print("用户进程的输出信息:{}".format(my_process.communicate()))
Python脚本实现top命令部分参数效果:
# !/usr/bin/env python
import time
import psutil
from datetime import datetime
from psutil._common import bytes2human as size
# 获取系统启动时间
print(f"{'-'*32} 系统时间 {'-'*32}")
uptime = datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S")
# 系统当前本地时间
now_time = time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime(time.time()))
print(f"系统启动时间: {uptime}\t系统本地时间:{now_time}")
# 获取系统用户
users_count = len(psutil.users())
users_list = ",".join([u.name for u in psutil.users()])
print(f"当前有{users_count}个用户:{users_list}")
print(f"{'-'*32} CPU信息 {'-'*32}")
# 物理cpu个数
cpu_count = psutil.cpu_count(logical=False)
# cpu内核个数
logical_cpu_count = psutil.cpu_count()
# cpu的使用率
cpu_percent = psutil.cpu_percent(1)
# cpu的平均负载
cpu_loadavg = " ".join([str(item) for item in psutil.getloadavg()])
print(f"CPU个数: {cpu_count}\t内核个数:{logical_cpu_count}\tcup使用率: {cpu_percent}%\tCPU负载参数:{cpu_loadavg}")
print(f"{'-'*32} 内存信息 {'-'*32}")
# 查看物理内存信息
memory = psutil.virtual_memory()
free = size(memory.free)
total = size(memory.total)
memory_percent = (memory.total - memory.free) / memory.total
print(f"总物理内存:{total}\t剩余物理内存:{free:10s}物理内存使用率:{int(memory_percent * 100)}%")
# 查看交换内存信息
swap = psutil.swap_memory()
free = size(swap.free)
total = size(swap.total)
swap_percent = (swap.total - swap.free) / swap.total
print(f"总交换内存:{total}\t剩余交换内存:{free:10s}交换内存使用率:{int(swap_percent * 100)}%")
print(f"{'-'*32} 网卡信息 {'-'*32}")
# 获取网卡信息,可以得到得到网卡属性,连接数,当前数据等信息
net = psutil.net_io_counters()
bytes_sent = size(net.bytes_recv)
bytes_rcvd = size(net.bytes_sent)
print(f"网卡接收数据:{bytes_rcvd}\t网卡发送数据:{bytes_sent}")
# 获取磁盘数据信息
print(f"{'-'*32} 磁盘信息 {'-'*32}")
io = psutil.disk_partitions()
for i in io:
try:
o = psutil.disk_usage(i.device)
print(f"设备:{i.device:12s}总容量:{size(o.total):6s}已用容量:{size(o.used):6s}可用容量:{size(o.free)}")
except PermissionError:
continue
print(f"{'-'*32} 进程信息 {'-'*32}")
# 查看系统全部进程
for pnum in psutil.pids():
p = psutil.Process(pnum)
p = psutil.Process(pnum)
print(f"进程名:{p.name():20.20s}内存利用率:{p.memory_percent():.2f}\t进程状态:{p.status():10s}创建时间:{datetime.fromtimestamp(p.create_time()):%Y-%m-%d %H:%M:%S}")
2. 自定义包¶
在 Python 中,模块(Module)就是一个个扩展名为.py 的源程序文件,所以我们之前创建的每一个python源程序文件都可以理解是模块。包(Package)就是一个个保存了模块和__init__.py文件的特殊目录。一个完整的Python项目通常都是基于模块和包的方式来组织代码。
2.1 包的初始化模块¶
在python中,一个目录下如果存在初始化模块__init__.py,则会被python系统默认为包。而初始化模块__init__.py的作用有2个:
- 可以编写一些导包时需要初始化执行的代码,这些代码会在包被导入时自动执行。
- 可以把包下面一些模块导入初始化模块
__init__.py中,实现简写效果。
注意:__init__.py,也可以是一个空文件。
2.2 导包路径¶
当你导入一个模块,Python 解析器对模块位置的搜索顺序是:
- 当前的工作目录
- PYTHONPATH(环境变量)中的每一个目录
- Python 默认的安装目录
所以在python开发过程中,上面3个路径可以认为python导包的默认起始导包路径。
2.2.1 绝对导包¶
从起始导包路径开始导入模块或包,这样的导包路径写法,就是绝对导包。常见写法如下:
# 写法1:
import 包名
# 用法1:
包名.模块名.变量
# 写法2:
import 包名.模块名
import 模块名
# 用法2:
包名.模块名.变量
模块名.变量
# 写法3:
from 包名 import 模块名
# 用法3:
模块名.变量
# 写法4:
from 包名.模块名 import 变量
# 用法4:
变量
2.2.2 相对导包¶
以当前代码文件作为起始路径,基于.或者..导入模块或包,这样的导包路径写法,就是相对导包。
注意:因为根目录默认是作为绝对导包的起始导包路径,所以相对导包路径的写法,不能应用于根目录下的文件中。
常见写法如下:
import 包名.模块
import 模块
from . import 模块
from .包 import 模块
from .包.模块 import 变量
from .. import 模块
from ..包 import 模块
from ..包.模块 import 变量
相对导包写法,会因为不同执行文件带来的路径差异,所以容易产生导包错误,因此开发中,能优先使用绝对导包。
2.3 批量导入¶
导包语句也可以在末尾使用使用逗号,一次性导入多个包/模块/变量,不管使用的是绝对导包,还是相对导包都可以。
import 包名1, 包名2, ...
import 包名1.模块名1, 包名1.模块名2, ..., 包名2.模块名1, 包名2.模块名2,...
from 包名 import 模块名1, 模块名2, ...
from 包名.模块名 import 变量1, 变量2, ...
2.4 别名调用¶
导包语句也可以在末尾使用as关键字,对包/模块/变量进行别名调用,不管使用的是绝对导包,还是相对导包都可以。
import 包名1 as 包别名1, 包2 as 包别名2, ...
import 包名1.模块名1 as 模块别名1, 包名1.模块名2 as 模块别名2, ....
from 包名 import 模块名1 as 模块别名1, 模块名2 as 模块别名2, ...
from 包名.模块名 import 变量1, 变量2, ...
2.5 全部导入¶
模块.py,代码:
2.6 限制导出¶
__init__.py,代码:
2.7 限制执行¶
在python中,每一个模块内部都会存在一个魔术变量__name__,__name__变量,在模块被其他文件导入时,值为模块名,如果模块被python解释器作为主程序执行时,则值为"__main__"。
模块.py,代码:
2.8 循环导包问题¶
在python开发过程中,经常会出现因为开发者没有很好的组织程序代码模块,而出现了a模块导入了b模块,b模块又导入了a模块,这种死循环的导包方式就是循环导包问题,也叫模块相互引用问题。
根目录/
├── application/
│ ├── a.py
│ ├── demo/
│ │ ├── b.py
│ │ └── __init__.py
│ └── __init__.py
└── main.py
main.py,代码:
a.py,代码:
b.py,代码:
上面的代码结构,在使用main.py,作为主程序运行时,会报错如下:
Traceback (most recent call last):
File "/home/moluo/Desktop/todolist/psdemo.py", line 1, in <module>
from application import a
File "/home/moluo/Desktop/todolist/application/a.py", line 1, in <module>
from .faker import b
File "/home/moluo/Desktop/todolist/application/faker/b.py", line 1, in <module>
from application.a import A
ImportError: cannot import name 'A' from partially initialized module 'application.a' (most likely due to a circular import) (/home/moluo/Desktop/todolist/application/a.py)
上面的错误,就是出现了循环导报问题。即a模块导入并调用了b模块,而b模块又随后调用了a模块。
循环导包的问题出现,往往是因为开发者没有有效的组织程序代码所致。因此,如果要解决此类问题,一般2种方案:
- 把导包冲突的代码合并到一个模块文件中,合并使用。
- 把导包语句写在局部作用域下,进行临时导包。这种方式,并非时时有效,而且属于治标不治本的方法
3. 模块发布¶
模块目录结构:
fakerDemo/
├── setup.py
├── person/
│ ├── mobile.py
│ ├── nickname.py
│ └── __init__.py
└── company/
├── company_name.py
├── job.py
└── __init__.py
setup.py,代码:
from distutils.core import setup
setup(
name="fakerDemo",
version="0.0.1",
description="faker demo module",
author="moluo",
py_modules=[
'email.mobile',
'person.nickname',
'company.company_name',
'company.job'
])
3.1 构建模块¶
目录效果:
.
├── build/
│ └── lib/
│ ├── company/
│ │ ├── company_name.py
│ │ ├── __init__.py
│ │ └── job.py
│ └── person/
│ ├── __init__.py
│ ├── mobile.py
│ └── nickname.py
├── company/
│ ├── company_name.py
│ ├── __init__.py
│ └── job.py
├── person/
│ ├── __init__.py
│ ├── mobile.py
│ └── nickname.py
└── setup.py
3.2 生成发布压缩包¶
打包后,生成最终发布压缩包fakerDemo-0.0.1.tar.gz。
.
├── build
│ └── lib
│ ├── company
│ │ ├── company_name.py
│ │ ├── __init__.py
│ │ └── job.py
│ └── person
│ ├── __init__.py
│ ├── mobile.py
│ └── nickname.py
├── company
│ ├── company_name.py
│ ├── __init__.py
│ └── job.py
├── dist
│ └── fakerDemo-0.0.1.tar.gz
├── MANIFEST
├── person
│ ├── __init__.py
│ ├── mobile.py
│ └── nickname.py
└── setup.py
Ok,经过上面的处理,我们就完成了模块的打包发布工作,接着来如果要把模块开源,则可以根据自己的需要上传到pypi/gitgub/gitee/gitlab或任意http服务器上,选择对应的开源协议,那将来就可以提供给任何人访问了。
在工作中,大部分的中大型互联网公司都会有一些自己内部人员开发给自己公司的模块或包,而这些包往往就在公司的内网中,所以如果遇到这种情况,同学们就需要注意,我们需要先入域(把自己开发的电脑连到公司内网)然后获取安装内部包/模块的权限即可。
3.3 安装模块¶
# 方法1:
pip install fakerDemo-0.0.1.tar.gz
# 方法2:
tar -zxvf fakerDemo-0.0.1.tar.gz
cd fakerDemo-0.0.1
python setup.py install
查看是否安装成功了。
3.4 卸载模块¶
3.5 模块上传¶
如果要上传模块打pypi平台上,则需要在平台上注册开发者账号并进行邮箱 验证。
注册地址:https://pypi.org/account/register/
注册了账号以后,还要继续安装第三方包twine,才能上传到pypi官方包列表网站中。
文档:https://packaging.python.org/en/latest/tutorials/packaging-projects/
安装完成以后,把上面的dist目录下的内容直接上传,并填写pipy官方平台上注册的账号密码即可。



