1、模块的概念
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py
文件就可以称之为一个模块(Module)。
那么,使用模块有哪些好处?
- 最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
- 使用模块还可以避免函数名和变量名冲突。每个模块有独立的命名空间,因此相同名字的函数和变量完全可以分别存在不同的模块中,所以,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。
2、模块的分类
模块分为三种:
- 内置标准模块(又称标准库)执行help('modules')查看所有python自带模块列表
- 第三方开源模块,可通过
pip install 模块名
联网安装 - 自定义模块
3、第三方开源模块
PyPi
https://pypi.org/
是Python的开源模块库,截止2020年7月31日 ,已经收录了253763个来自全世界Python开发者贡献的模块,几乎涵盖了你想用Python做的任何事情。 事实上每个Python开发者,只要注册一个账号就可以往这个平台上传你自己的模块,这样全世界的开发者都可以容易的下载并使用你的模块。
3.1、通过setup.py安装
直接在上面的页面上点 Download files
,下载后,解压并进入目录,执行以下命令完成安装。
1 | python setup.py build #编译源码 python setup.py install #安装源码 |
3.2、通过pip安装
执行
1 | pip3 install requests #paramiko 是模块名 |
pip命令会自动下载模块包并完成安装。
软件一般会被自动安装你python安装目录的这个子目录里
1 | \Python安装目录\Lib\site-packages |
pip命令默认会连接在国外的python官方服务器下载,速度比较慢,建议更换为清华大学源。
更多软件源参考本站文章:
国内软件源对比
https://blog.tsinbei.com/archives/238/
更换软件源教程参考:
服务器优化(二)更换软件源
https://blog.tsinbei.com/archives/237/
4、模块导入和调用
1 | import random #导入整个random模块 from random import randint #导入 random 模块里的 randint 函数 from random import randint as suijishu ##导入 random 模块里的 randint 函数并重命名为 suijishu from random import * #导入random模块下的所有方法(调用时无需输入random这个前缀),非常不建议使用 random.xxx #调用 |
注意:模块一旦被调用,即相当于执行了另外一个py文件里的代码
5、自定义模块
创建一个.py文件,就可以称之为模块,就可以在另外一个程序里导入
自己写的模块只能在当前路径下的程序里才能导入,换一个目录再导入自己的模块就报错找不到模块,这与导入模块的查找路径有关:
此处内容需要评论回复(自动审核)或加入 QQ 技术交流群(立即获得内容)后方可阅读。赞助(二维码在文章下方)后联系作者可一次性解锁所有(包括之后的新文章)。
你导入一个模块时,Python解释器会按照上面列表顺序去依次到每个目录下去匹配你要导入的模块名,只要在一个目录下匹配到了该模块名,就立刻导入,不再继续往后找。
注意列表第一个元素是当前目录,所以你自己定义的模块在当前目录会被优先导入。
我们自己创建的模块若想在任何地方都能调用,那就得确保你的模块文件至少在模块路径的查找列表中。
我们一般把自己写的模块放在一个带有“site-packages”字样的目录里,我们从网上下载安装的各种第三方的模块一般都放在这个目录。
6、调用
6.1、os模块
os模块提供了很多允许你的程序与操作系统直接交互的功能
1 | import os # 导入模块 os.getcwd() # 得到当前工作目录,即当前Python脚本工作的目录路径 os.listdir() # 返回指定目录下的所有文件和目录名 os.remove() # 删除一个文件 os.removedirs(r“c:\python”) # 删除多个目录 os.path.isfile() # 检查路径是否为文件 os.path.isdir() # 检查路径是否为目录 os.path.isabs() # 是否是绝对路径 os.path.exists() # 检查路径是否存在 os.path.split() # 获得路径的目录名和文件名 os.path.splitext() # 分离文件扩展名 os.path.dirname() # 获取路径目录名 os.path.abspath() # 获得绝对路径 os.path.basename() # 获取文件名 os.system() # 运行shell命令 os.getenv("HOME") # 读取操作系统环境变量 os.environ # 返回操作系统所有的环境变量 os.environ.setdefault('HOME','/home/alex') # 设置系统环境变量 os.rename(old,new) # 重命名 os.makedirs(r"c:\python\test") # 创建多级目录 os.mkdir("test") # 创建单个目录 os.stat(file) # 获取文件属性 os.chmod(file) # 修改文件权限与时间戳 os.path.getsize(filename) # 获取文件大小 os.chdir(dirname) # 改变工作目录到dirname os.get_terminal_size() # 获取当前终端的大小 os.kill(10884,signal.SIGKILL) # 关闭进程 |
6.2、sys模块
1 | import sys sys.argv #命令行参数List,第一个元素是程序本身路径 sys.exit(n) #退出程序,正常退出时exit(0) sys.version #获取Python解释程序的版本信息 sys.maxint #最大的Int值 sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform #返回操作系统平台名称 sys.stdout.write('please:') #标准输出 , 引出进度条的例子, 注,在py3上不行,可以用print代替 val = sys.stdin.readline()[:-1] #标准输入 sys.getrecursionlimit() #获取最大递归层数 sys.setrecursionlimit(1200) #设置最大递归层数 sys.getdefaultencoding() #获取解释器默认编码 sys.getfilesystemencoding #获取内存数据存到文件里的默认编码 |
6.3、time模块
在Python中,通常有这几种方式来表示时间:
- 时间戳(timestamp), 表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。例子:
1596258440.116188
- 格式化的时间字符串,比如
2020-08-01 13:07:20
- 元组(struct_time)共九个元素。由于Python的time模块实现主要调用C库,所以各个平台可能有所不同,Windows上:time.struct_time(tm_year=2020, tm_mon=8, tm_mday=1, tm_hour=13, tm_min=10, tm_sec=43, tm_wday=5, tm_yday=214, tm_isdst=0)
索引(Index) | 属性(Attribute) | 值(Values) |
---|---|---|
0 | tm_year(年) | 比如2020 |
1 | tm_mon(月) | 1 - 12 |
2 | tm_mday(日) | 1 - 31 |
3 | tm_hour(时) | 0 - 23 |
4 | tm_min(分) | 0 - 59 |
5 | tm_sec(秒) | 0 - 59 |
6 | tm_wday(weekday) | 0 - 6(0表示周一) |
7 | tm_yday(一年中的第几天) | 1 - 366 |
8 | tm_isdst(是否是夏令时) | 默认为-1 |
UTC时间
UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8,又称东8区。DST(Daylight Saving Time)即夏令时。
time模块的方法
- time.localtime([secs]):将一个时间戳转换为当前时区的struct_time。若secs参数未提供,则以当前时间为准。
- time.gmtime([secs]):和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
- time.time():返回当前时间的时间戳。
- time.mktime(t):将一个struct_time转化为时间戳。
- time.sleep(secs):线程推迟指定的时间运行,单位为秒。
- time.asctime([t]):把一个表示时间的元组或者struct_time表示为这种形式:’Sun Oct 1 12:04:38 2019’。如果没有参数,将会将time.localtime()作为参数传入。
- time.ctime([secs]):把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。
- time.strftime(format[, t]):把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。
- time.strptime(string[,format]):把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。
6.4、datetime模块
相比于time模块,datetime模块的接口则更直观、更容易调用
datetime模块定义了下面这几个类:
- datetime.date:表示日期的类。常用的属性有year, month, day;
- datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond;
- datetime.datetime:表示日期时间。
- datetime.timedelta:表示时间间隔,即两个时间点之间的长度。
- datetime.tzinfo:与时区有关的相关信息。(这里不详细充分讨论该类,感兴趣的童鞋可以参考python手册)
我们需要记住的方法仅以下几个:
- d=datetime.datetime.now()
返回当前的datetime日期类型
1 | d.timestamp(),d.today(),d.year,d.timetuple()等方法可以调用 |
- datetime.date.fromtimestamp()
把一个时间戳转为datetime日期类型
- 时间运算
1 | >>> print(datetime.datetime.now()) 2020-08-01 16:30:24.940736 >>> datetime.datetime.now() datetime.datetime(2020, 8, 1, 16, 30, 42, 475749) >>> print(datetime.datetime.now() + datetime.timedelta(4)) #当前时间 +4天 2020-08-05 16:31:04.921738 >>> print(datetime.datetime.now() + datetime.timedelta(hours=4)) #当前时间 +4小时 2020-08-01 20:31:19.610740 |
- 时间替换
1 | >>> print(d.replace(year=2999,month=11,day=30)) 2999-11-30 16:28:37.857495 |
6.5、random模块
程序中有很多地方需要用到随机字符,比如登录网站的随机验证码,通过random模块可以很容易生成随机字符串
1 | >>> import random >>> random.randrange(1,10) #返回1-10之间的一个随机数,不包括10 6 >>> random.randint(1,10) #返回1-10之间的一个随机数,包括10 6 >>> random.randrange(0, 100, 2) #随机选取0到100间的偶数 76 >>> random.random() #返回一个随机浮点数 0.9257294868672783 >>> random.choice('https://blog.tsinbei.com') #返回一个给定数据集合中的随机字符 'z' >>> random.sample('https://blog.tsinbei.com',3) #从多个字符中选取特定数量的字符 ['g', 'h', 'o'] #生成随机字符串 >>> import string >>> ''.join(random.sample(string.ascii_lowercase + string.digits, 8)) 'clvebqw4' #重新排序 >>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> random.shuffle(a) >>> a [1, 9, 7, 0, 5, 8, 4, 2, 3, 6] |
6.6、pickle和json模块
pickle和json是用于序列化的两个模块。
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
pickle模块提供了四个功能:dumps、dump、loads、load
1 | import pickle data = {'test':123,'url':'https://blog.tsinbei.com'} # pickle.dumps 将数据通过特殊的形式转换位只有python语言认识的字符串 p_str = pickle.dumps(data) # 注意dumps会把数据变成bytes格式 print(p_str) # pickle.dump 将数据通过特殊的形式转换位只有python语言认识的字符串,并写入文件 with open('result.pk',"wb") as fp: # 文件 result.pk 可以改成其他名字和后缀 pickle.dump(data,fp) # pickle.load 从文件里加载 with open('result.pk',"rb") as f: d = pickle.load(f) print(d) |
Json模块也提供了四个功能:dumps、dump、loads、load,用法跟pickle一致
1 | import json data = {'test':123,'url':'https://blog.tsinbei.com'} # json.dumps 将数据通过特殊的形式转换位所有程序语言都认识的字符串 j_str = json.dumps(data) # 注意json dumps生成的是字符串,不是bytes print(j_str) #dump入文件 with open('config.json','w') as fp: json.dump(data,fp) #从文件里load with open("config.json") as f: d = json.load(f) print(d) |
6.7、hashlib模块
Python3.x里用hashlib代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD5 算法
1 | import hashlib # md5 md5 = hashlib.md5() md5.update(b"https://blog.tsinbei.com") print(md5.digest()) # 返回2进制格式的hash值 print(md5.hexdigest()) # 返回16进制格式的hash值 # 如果数据量很大可以分多次调用update(),最后计算结果一样 md5 = hashlib.md5() md5.update(b"https://") md5.update(b"blog.tsinbei.com") print(md5.hexdigest()) # 返回16进制格式的hash值 # sha1 s1 = hashlib.sha1() s1.update(b"blog.tsinbei.com") print(s1.hexdigest()) # sha256 s256 = hashlib.sha256() s256.update(b"blog.tsinbei.com") print(s256.hexdigest()) # sha512 s512 = hashlib.sha512() s512.update(b"blog.tsinbei.com") print(s512.hexdigest()) |
6.8、shutil模块
1 | import shutil shutil.copyfileobj(fsrc, fdst[,length]) # 将文件内容拷贝到另一个文件中 shutil.copyfile(src, dst) # 拷贝文件 shutil.copymode(src, dst) # 仅拷贝权限。内容、组、用户均不变 shutil.copystat(src, dst) # 仅拷贝状态的信息,包括:mode bits, atime, mtime, flags shutil.copy(src, dst) # 拷贝文件和权限 shutil.copy2(src, dst) # 拷贝文件和状态信息 shutil.ignore_patterns(*patterns) shutil.copytree(src, dst, symlinks=False, ignore=None) # 递归的去拷贝文件夹 shutil.rmtree(path[, ignore_errors[, onerror]]) # 递归删除文件,删除整个目录(回收站无法找回) shutil.move(src, dst) # 递归的去移动文件 |
其他函数:
shutil.make_archive(base_name, format,…)
创建压缩包并返回文件路径,例如:zip、tar
可选参数如下:
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak =>保存至当前路径
如:/tmp/data_bak =>保存至/tmp/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
1 | import shutil #将当前目录下的data文件夹下的文件打包放置当前程序目录 ret = shutil.make_archive("data_bak", 'gztar', root_dir='data') #将C盘data文件夹下的文件打包放置C:/tmp/目录 ret = shutil.make_archive("C:/tmp/data_bak", 'gztar', root_dir='C:/data') |
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,例:
1 | import zipfile # 压缩 z = zipfile.ZipFile('abc.zip', 'w') z.write('a.log') z.close() # 解压 z = zipfile.ZipFile('abc.zip', 'r') z.extractall(path='.') z.close() |
1 | import tarfile # 压缩 t = tarfile.open('/tmp/egon.tar','w') t.add('/test1/a.py',arcname='a.bak') t.add('/test1/b.py',arcname='b.bak') t.close() # 解压 t = tarfile.open('/tmp/egon.tar','r') t.extractall('/egon') t.close() |
6.9、re模块
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能
正则表达式语法可以参考菜鸟教程:
此处内容需要评论回复(自动审核)或加入 QQ 技术交流群(立即获得内容)后方可阅读。赞助(二维码在文章下方)后联系作者可一次性解锁所有(包括之后的新文章)。
re的匹配语法有以下几种:
- re.match 从头开始匹配
- re.search 匹配包含
- re.findall 把所有匹配到的字符放到以列表中的元素返回
- re.split 以匹配到的字符当做列表分隔符
- re.sub 匹配字符并替换
- re.fullmatch 全部匹配
re.match(pattern, string, flags=0)
从起始位置开始根据模型去字符串中匹配指定内容,匹配单个
- pattern 正则表达式
- string 要匹配的字符串
- flags 标志位,用于控制正则表达式的匹配方式
1 | import re obj = re.match('\d+', '123uuasf456') #如果能匹配到就返回一个可调用的对象,否则返回None if obj: print(obj.group()) # 输出结果:123 |
Flags标志符
- re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
- re.M(MULTILINE): 多行模式,改变’^’和’$’的行为
- re.S(DOTALL): 使 . 匹配包括换行在内的所有字符
- re.X(re.VERBOSE) 可以给你的表达式写注释,使其更可读.
re.search(pattern, string, flags=0)
根据模型去字符串中匹配指定内容,匹配单个
1 | import re obj = re.search('\d+', 'u123uu888asf') if obj: print(obj.group()) # 输出结果:123 |
re.findall(pattern, string, flags=0)
match and search均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。
1 | import re obj = re.findall('\d+', 'fa123uu888asf') print(obj) # 输出结果:['123', '888'] |
re.sub(pattern, repl, string, count=0, flags=0)
用于替换匹配的字符串,比str.replace功能更加强大
1 | >>> re.sub('[a-z]+','666','blog.tsinbei.com 六六六',) '666.666.666 六六六' >>> re.sub('\d+','|', 'alex22wupeiqi33oldboy55',count=2) 'alex|wupeiqi|oldboy55' |
re.split(pattern, string, maxsplit=0, flags=0)
用匹配到的值做为分割点,把值分割成列表
1 | >>> s='9-2*5/3+7/3*99/4*2998+10*568/14' >>> re.split('[\*\-\/\+]',s) ['9', '2', '5', '3', '7', '3', '99', '4', '2998', '10', '568', '14'] >>> re.split('[\*\-\/\+]',s,3) ['9', '2', '5', '3+7/3*99/4*2998+10*568/14'] |
re.fullmatch(pattern, string, flags=0)
整个字符串匹配成功就返回re object, 否则返回None
1 | re.fullmatch('\w+@\w+\.(com|cn|edu)',"[email protected]") |
7、鸣谢
转载自:
Zeruns's Blog
Python 理论知识(六)模块的导入和使用
评论