Python-包与常用模块(2)

目录

当项目越来越大,模块文件里功能越来越多,这时候把功能全部写在一个模块里就不是很好维护了,于是就有了包的概念,将功能分不同的文件和放在不同的包中,每个包里面存在一个__init__文件,用于导入本层包内所有模块

包是模块一的一种形式,本质上就是一个含有.py的文件夹

导入包 发生了三件事情

  1. 创建一个包的名称空间
  2. 指向包下面的py文件,将执行产生的名字放于包名称空间中,即包名称空间中存放的名字都是来自于py文件中
  3. 在当前执行文件中拿到一个包名 指向包的名称空间
# 导入包就相当于导入包内的__init__文件,执行的时候以执行文件路径为搜索路径
# 对于用户来说 导入包不能改变调用方式
import aaa


aaa.m2()
aaa.m3()

导入包内包

Python-包与常用模块(2)

导入包内包的话 要在第一层包__init__文件里面导入第二层包的模块和方法,这样最外面执行文件可以不用改变调用方式

相对导入和绝对导入


# 绝对导入
from aaa.m1 import m1
from aaa.m2 import m2
from aaa.bbb import m3
from aaa.bbb import m4


# 相对导入
from .m1 import m1
from .m2 import m2
from .bbb import m3
from .bbb import m4


# 相对导入
# 导入包内包的话 也要在第一层包__init__文件里面导入第二层包的方法,这样,最外面执行文件可以不用改变调用方式导入
from ..bbb.m3 import m3
from ..bbb.m4 import m4

注意事项

  1. 包内的所有文件都是被导入使用,而不是被直接运行的。
  2. 包内部模块之间的导入可以使用绝对导入与相对导入,使用相对导入更好一点。
  3. 只有在文件被当做模块导入时才能使用相对导入的方法
  4. 凡是在导入时是相对导入时,.的左边必须是一个包

time模块

time模块 主要提欧共了三种不同类型的时间,三种不同类型可以相互转换

方法 描述
time.time() 时间戳形式
time.strftime('%Y-%m-%d %X') 最常用 格式化为 2019-09-27 22:53:19
time.localtime() 结构化时间
import time

# 时间戳形式
print(time.time()) 

# 格式化时间
print(time.strftime('%Y-%m-%d %X'))

# 结构化时间
print(time.localtime())


# 结构化时间 --》 格式化时间
struct_time = time.localtime(3600*24*365)
print(time.strftime('%Y-%m-%d %X',struct_time))


# 格式化时间 --》 结构化时间
format_time = time.strftime('%Y-%m-%d %X')
print(time.strptime(format_time,'%Y-%m-%d %X'))


# 结构化时间 --》 时间戳
struct_time = time.localtime(3600*24*365)
print(time.mktime(struct_time))

# 时间戳 --》 结构化时间
time_stamp = time.time()
print(time.localtime(time_stamp))

datetime模块

datetime模块:时间上可以加减

import datetime

now = datetime.datetime.now()
print(now)
# 2019-09-28 19:53:31.924508

# 默认3天
print(now + datetime.timedelta(3))
# 加3周
print(now + datetime.timedelta(weeks=3))
# 加3小时
print(now + datetime.timedelta(hours=3))
# 减3小时
print(now - datetime.timedelta(hours=3))
print(now + datetime.timedelta(hours=-3))

print(now.replace(year=1949, month=10, day=1, hour=10, minute=1, second=0, microsecond=0))
# 1949-10-01 10:01:00

random模块

random 主要用于生成随机数

方法 描述
random.random() 生成 0-1 的随机数
random.randint(1,10) 生成指定序列的随机数
random.randrange(1,3) 生成指定序列的随机数
random.shuffle([1,2,45,6,8]) 随机打乱顺序
import random

# 打印 0-1 的随机数,并不是真正的随机
print(random.random())
# 0.6629366744271181

# 打印随机数(1-10)
print(random.randint(1,10))
# 6

# 大于等于1且小于3的整数
print(random.randrange(1,3))
# 1

# 大于1小于3的小数
print(random.uniform(1,3))
# 2.0132434909012336

# 随机,打乱顺序
lis = [1,4,5,7,]
random.shuffle(lis)
print(lis)

print(random.choice(lis))
# 4

argparse 模块

argparse
这个模块可以帮助我们解析一些命令行传过来的参数并做一些处理
就像这样

python run.py --agt 6 --usr 1 --max_turn 40 --episodes 150 --movie_kb_path .\deep_dialog\data\movie_kb.1k.p --run_mode 2

def add_parser(parser):
    # 添加一些可选参数
    parser.add_argument("-dog", dest="dog", default="输入一只狗的名字", type=str, help="输入一只狗的名字/命令")
    parser.add_argument("-u", "--ssh_user", dest="ssh_user", required=False, help="shh的用户名, 比如: root")
    parser.add_argument("-tn", "--thread_num", dest="thread_num", required=False, help="并发线程数, 比如: 10")

def init_base():
    # 声明一个参数解析对象
    parser = argparse.ArgumentParser(prog="bible", description="统一自动化工具")
    subparser = parser.add_subparsers(title="统一自动化工具", description="可用功能", help="功能具体使用", dest="action")

    # 功能模板
    template_parser = subparser.add_parser("template",help="功能")
    add_parser(template_parser)

    # #解析参数
    args = parser.parse_args()

init_base()

--dog - 代表一个可选参数 也可以写成一个- -dog
dest - 保存到ArgumentParser对象时的 参数名,
default - 默认值,如果不输入参数默认显示到终端的名字
type - 将输入的字符串转化成改数据类型
help - 输入--help 时获得的帮助
required - 该命令行选项是否可以省略(只针对可选参数)。
action - 在命令行遇到该参数时采取的基本动作类型。

[root@localhost]# python test.py -h
usage: bible [-h] {template} ...

统一自动化工具

optional arguments:
  -h, --help  show this help message and exit

统一自动化工具:
  可用功能

  {template}  功能具体使用
    template  功能

    
[root@localhost]# python test.py template -h
usage: bible template [-h] [-dog DOG] [-u SSH_USER] [-tn THREAD_NUM]

optional arguments:
  -h, --help            show this help message and exit
  -dog DOG              输入一只狗的名字/命令
  -u SSH_USER, --ssh_user SSH_USER
                        shh的用户名, 比如: root
  -tn THREAD_NUM, --thread_num THREAD_NUM
                        并发线程数, 比如: 10

hashlib模块和hmac模块

hashlib 模块主要对字符串加密
hmac 模块不仅对字符加密,还加上了密钥,更加安全

import hashlib
import hmac

# hashlib
m = hashlib.md5()
m.update(b"qinyj123")
res = m.hexdigest()
print(res)
# a18973e94364927b08e7509dd3dbfde2      对于不同的字符而言,用不重复的密码


# hmac
m = hmac.new(b"qin1yj123123")       # 加了一层密码
m.update(b"qinyj123")
res = m.hexdigest()
print(res)
# df1a1fcfaa4ec033406fe608b08ba45a

typing模块

typing 函数主要与函数一起连用,控制函数参数的数据类型用的,提供了基础数据类型之外的数据类型

lt = [1,2,3,4]
print(type(lt) is list)
# True

from typing import Iterable,Generator

def func(x:int, lt:Iterable) -> list:
    return lt

res = func(10,lt)
print(res)
# [1, 2, 3, 4]

re模块

正则表达式,去字符串找符合某种特点的字符串

元字符 描述
^ 匹配规则:以什么什么开头
$ 匹配规则:以什么什么结尾
. 匹配任意字符
\d 匹配 数字的
\D 匹配 非数字的
\w 匹配 非空
\W 匹配 空的
\s 匹配 空
\S 匹配 非空
+ 匹配 + 号前面的一个字符至少匹配0个
? 匹配 ? 号前面的一个字符至少匹配0-1个
* 匹配 * 号前面的一个字符至少匹配0个
[] 匹配 [] 内的字符
[^] [^] 内的字符都不匹配
| 匹配 规则xx 或 规则xx
{13} 匹配 前面字符13个,比如手机号
{1,2} 匹配 前面字符2个
贪婪模式 非贪婪模式
.* 一直匹配,直到匹配完毕 .*?进入非贪婪模式,匹配特定的

最常用的就是以下修饰符了

修饰符 描述
re.l 让匹配部分大小写
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
import re

# bug,应该都会打印出来
# s = "dhjsfsnfsnk"
# res = re.findall("",s)
# print(res)

# 以下全部是元字符
# 1. ^   以什么什么开头
s = "sndkjbsfkbs"
print(re.findall("^sn",s))
# ['sn']
print(re.findall("^fkb",s))
# []


# 2. $ 以什么什么结尾
s = "sndkjbsfkbs"
print(re.findall("bs$",s))
# ['bs']
print(re.findall("dmskdhs$",s))
# []

# 3. . 匹配任意字符
s = "abc红abc"
print(re.findall(".",s))
# ['a', 'b', 'c', '红', 'a', 'b', 'c']
print(re.findall(".add",s))
# []


# 4. \d 匹配数字
s = "sndkjbsfkbs13275242sadbhajsv"
print(re.findall("\d",s))
# ['1', '3', '2', '7', '5', '2', '4', '2']


# 5. \w 匹配非空即不打印空,包括数字字母下划线
s = "abc"
print(re.findall("\w",s))
# ['a', 'b', 'c']
s = "a b c,dsds"
print(re.findall("\w",s))
# ['a', 'b', 'c']

# 6.\s 匹配空
s = "abc"
print(re.findall("\s",s))
s = "a b c,dsds"
print(re.findall("\s",s))
# [' ', ' ']

# 7. \D 匹配非数字
s = "abc123"
print(re.findall("\D",s))
# ['a', 'b', 'c']


# 8. \W 匹配空的
s = "a b c"
print(re.findall("\W",s))
# [' ', ' ']


# 9. \S 匹配非空的
s = "a b c"
print(re.findall("\S",s))
# ['a', 'b', 'c']

# 10. + 匹配 + 号前面的那一个字符 加上其他字符至少有一个就打印
s = "12345"
print(re.findall("23+",s))
# ['23']

# 11. ? 前面的一个字符0-1 个即可
s = "dafxsehtrnt"
print(re.findall("dat?",s))
# ['f', 'fl']

# 12. * 前面的一个字符至少0个
s = "dafxsehtrnt"
print(re.findall("@*",s))
# ['', '', '', '', '', '', '', '', '', '', '', '']

# 13. [] 只匹配中括号内的
s = "dmksff"
print(re.findall("[dmks]",s))
# ['d', 'm', 'k', 's']

# 14. [^] 中括号内的不匹配
s = "dfa"
print(re.findall("[^a]",s))
# ['d', 'f']

# 15. | 或
s = "dsajbfasfbia"
print(re.findall("dsa|bia",s))
# ['dsa', 'bia']

# 16. {2} 匹配前面的2个字符
s = "fsdsfs"
print(re.findall("fs{1,2}",s))
# ['fs', 'fs']



# 贪婪模式
# .*
s = "saaasaaas"         # 找到最后
print(re.findall("s.*s",s))
# ['saaasaaas']


# 非贪婪模式 .*?
s = "saaasaaas"         # 找到第一个不找了
print(re.findall("s.*?s",s))
# ['saaas']


# 匹配邮箱
# s = '#@#@#@nickchen121@163.com$$$$////nick@qq.com$$#$#$[]]2287273393@162.com@$2423423lksdlfj#'
s = "{|}{}|PP~#&(*$(^1342542daj@162.com/,/<>>]]}{}nicsh_snn@qq.comdsff1232//1213#$%^^asnjkgsa123@gmail.comdwanua"
print(re.findall("\w+@\w+.com",s))
# ['1342542daj@162.com', 'nicsh_snn@qq.com', 'asnjkgsa123@gmail.com']

# compile
s = '3728427482097jkcbdscvdb}:{}:{'
email_pattern = re.compile("\w+@\w+.com")
phone_pattern = re.compile("\d{13}")
print(re.findall(phone_pattern,s))
# ['3728427482097']

# match 从开头找一个,找到不找了报错
# s = 'ab abcddd abc'
# res = re.match('ab*', s)
# print(res.group())


# search 从字符串找一个就不找了
s = 'ab abcddd abc'
res = re.search("abcd*",s)
print(res.group())

# split 不匹配数字,以数字为分隔符
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.split("\d+",s))
# ['ab', 'abcddd', 'abcasdfjlasjdk', 'l', 'lk', 'j', 'kl', 'kl', 'k', 'j', 'kl', 'j', 'lkj']

# sub == replace
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.sub("\d+","",s))
# ababcdddabcasdfjlasjdkllkjklklkjkljlkj

# subn  替换了多少次
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.subn("\d+","",s))
# ('ababcdddabcasdfjlasjdkllkjklklkjkljlkj', 12)






# 修饰符  re.S  会让.匹配换行符
s = '''abc
abcabc*abc
'''

print(re.findall("abc.abc",s))
# ['abc*abc']
print(re.findall("abc.abc",s,re.S))
# ['abc\nabc', 'abc*abc']

# 无名分组  只要括号里的
s = 'abc abcd abcdd'
print(re.findall("a(.)c(d)",s))
# [('b', 'd'), ('b', 'd')]

# 有名分组
s = 'abc abcd abcdd'
print(re.search("a(?P<name1>.)c(?P<name2>d)",s).groupdict())
# {'name1': 'b', 'name2': 'd'}

# 超高级用法
s = 'abc123abc123'
print(re.sub("c(\d+)a"," ",s))
# ab bc123
print(re.sub("c(?P<name1>\d+)a","  \g<name1>  " ,s))
# ab  123  bc123
上一篇:9.28 包/time/datetime/random/hashlib/hmac/typing/requests/re模块


下一篇:day 17 小结