zoukankan      html  css  js  c++  java
  • 第二模块_第2章节(第四章节)

    第四章节

    1、什么是模块

    在Python中,一个.py文件就可以称之为一个模块

    2、模块的好处

    最大的好处是大大提高了代码的可维护性

    使用模块还可以避免函数名和变量名冲突

    3、模块的分类

    1.标准模块(标准库、内置模块)

    有近300个,随时可以调用

    2.第三方模块

    近18w个左右

    需要单独安装  pip install

    3.自定义模块

    自己写的

    模块的导入和调用

    import

    from os import rename,path,replace

    rename()

    path()

    replace()

    模块的导入要写在首行

    模块的调用方法:

    mport module
    
    from module import xx
    
    from module.xx.xx import xx as rename  
    
    from module.xx.xx import *

    自定义模块

    模块的查找路径:

    全局能导入:

    把文件放到第三方模块的路径下,就可以实现全局调用

    第三方模块的安装和使用

    https://pypi.org/

    直接pip安装

    pip命令会自动下载模块包病完成安装

    软件一般会被自动安装你python安装目录的这个字目录里:

    /your_python_install_path/3.6/lib/python3.6/site-packages
    sudo pip install -i http://pypi.douban.com/simple/ alex_sayhi --trusted-host pypi.douban.com   #alex_sayhi是模块名

    OS模块

    程序与系统的交互功能

    得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd

    >>> os.getcwd()
    'C:\Users\hanjj20688'
    >>>

    返回指定目录下的所有文件和目录名:os.listdir()

    >>> os.listdir()
    ['.PyCharm2018.3', '3D Objects', 'AppData', 'Application Data', 'Contacts', 'Cookies', 'Desktop', 'Documents', 'Downloads', 'Evernote', 'Favorites', 'IntelGraphicsProfiles', 'Links', 'Local Settings', 'MicrosoftEdgeBackups', 'Music', 'My Documents', 'NetHood', 'NTUSER.DAT', 'ntuser.dat.LOG1', 'ntuser.dat.LOG2', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TM.blf', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000001.regtrans-ms', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000002.regtrans-ms', 'ntuser.ini', 'ntuser.pol', 'Pictures', 'PrintHood', 'Recent', 'Saved Games', 'Searches', 'SendTo', 'Templates', 'Videos', '「开始」菜单']
    >>>

    获取当前路径下的文件

    >>> os.listdir(".")
    ['.PyCharm2018.3', '3D Objects', 'AppData', 'Application Data', 'Contacts', 'Cookies', 'Desktop', 'Documents', 'Downloads', 'Evernote', 'Favorites', 'IntelGraphicsProfiles', 'Links', 'Local Settings', 'MicrosoftEdgeBackups', 'Music', 'My Documents', 'NetHood', 'NTUSER.DAT', 'ntuser.dat.LOG1', 'ntuser.dat.LOG2', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TM.blf', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000001.regtrans-ms', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000002.regtrans-ms', 'ntuser.ini', 'ntuser.pol', 'Pictures', 'PrintHood', 'Recent', 'Saved Games', 'Searches', 'SendTo', 'Templates', 'test', 'test.txt', 'Videos', '「开始」菜单']
    >>>

    函数用来删除一个文件:os.remove()

    >>> os.remove("试验用.txt")
    >>> os.remove("那些人.txt")

    删除多个目录:os.removedirs(r“c:python”)

    检验给出的路径是否是一个文件:os.path.isfile()

    检验给出的路径是否是一个目录:os.path.isdir()

    判断是否是绝对路径:os.path.isabs()

    检验给出的路径是否真地存:os.path.exists()

    返回一个路径的目录名和文件名:os.path.split() e.g os.path.split('/home/swaroop/byte/code/poem.txt') 结果:('/home/swaroop/byte/code', 'poem.txt') 

    分离扩展名:os.path.splitext() e.g os.path.splitext('/usr/local/test.py') 结果:('/usr/local/test', '.py')

    获取路径名:os.path.dirname()

    获得绝对路径: os.path.abspath()  

    打印当前脚本所在的路径,包含文件名【打印的是绝对路径】

    import   os
    print(__file__)
    

    输出

    D:pyLearningvenvScriptspython.exe D:/py/Learning/第四模块/account.json.py
    D:/py/Learning/第四模块/account.json.py

    获取文件名:os.path.basename()

    运行shell命令: os.system()

    读取操作系统环境变量HOME的值:os.getenv("HOME") 

    返回操作系统所有的环境变量: os.environ 

    设置系统环境变量,仅程序运行时有效:os.environ.setdefault('HOME','/home/alex')

    给出当前平台使用的行终止符:os.linesep Windows使用' ',Linux and MAC使用' '

    指示你正在使用的平台:os.name 对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'

    重命名:os.rename(old, new)

    >>> os.listdir(".")
    ['.PyCharm2018.3', '3D Objects', 'AppData', 'Application Data', 'Contacts', 'Cookies', 'Desktop', 'Documents', 'Downloads', 'Evernote', 'Favorites', 'IntelGraphicsProfiles', 'Links', 'Local Settings', 'MicrosoftEdgeBackups', 'Music', 'My Documents', 'NetHood', 'NTUSER.DAT', 'ntuser.dat.LOG1', 'ntuser.dat.LOG2', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TM.blf', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000001.regtrans-ms', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000002.regtrans-ms', 'ntuser.ini', 'ntuser.pol', 'Pictures', 'PrintHood', 'Recent', 'Saved Games', 'Searches', 'SendTo', 'Templates', 'test', 'test.txt', 'Videos', '「开始」菜单']
    >>> os.rename("test.txt","test22.txt")
    >>> os.listdir(".")
    ['.PyCharm2018.3', '3D Objects', 'AppData', 'Application Data', 'Contacts', 'Cookies', 'Desktop', 'Documents', 'Downloads', 'Evernote', 'Favorites', 'IntelGraphicsProfiles', 'Links', 'Local Settings', 'MicrosoftEdgeBackups', 'Music', 'My Documents', 'NetHood', 'NTUSER.DAT', 'ntuser.dat.LOG1', 'ntuser.dat.LOG2', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TM.blf', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000001.regtrans-ms', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000002.regtrans-ms', 'ntuser.ini', 'ntuser.pol', 'Pictures', 'PrintHood', 'Recent', 'Saved Games', 'Searches', 'SendTo', 'Templates', 'test', 'test22.txt', 'Videos', '「开始」菜单']

    创建多级目录:os.makedirs(r“c:python est”)

    创建单个目录:os.mkdir(“test”)

    获取文件属性:os.stat(file)

    >>> os.listdir(".")
    ['.PyCharm2018.3', '3D Objects', 'AppData', 'Application Data', 'Contacts', 'Cookies', 'Desktop', 'Documents', 'Downloads', 'Evernote', 'Favorites', 'IntelGraphicsProfiles', 'Links', 'Local Settings', 'MicrosoftEdgeBackups', 'Music', 'My Documents', 'NetHood', 'NTUSER.DAT', 'ntuser.dat.LOG1', 'ntuser.dat.LOG2', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TM.blf', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000001.regtrans-ms', 'NTUSER.DAT{8ebe95f7-3dcb-11e8-a9d9-7cfe90913f50}.TMContainer00000000000000000002.regtrans-ms', 'ntuser.ini', 'ntuser.pol', 'Pictures', 'PrintHood', 'Recent', 'Saved Games', 'Searches', 'SendTo', 'Templates', 'test', 'test22.txt', 'Videos', '「开始」菜单']
    >>> os.stat("test22.txt")
    os.stat_result(st_mode=33206, st_ino=22799473113716506, st_dev=906384342, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1568032366, st_mtime=1568032366, st_ctime=1568032366)
    >>>

    修改文件权限与时间戳:os.chmod(file)

    获取文件大小:os.path.getsize(filename)

    结合目录名与文件名:os.path.join(dir,filename)

    改变工作目录到dirname: os.chdir(dirname)

    获取当前终端的大小: os.get_terminal_size()

    杀死进程: os.kill(10884,signal.SIGKILL)

     

    sys模块

    time模块

    对时间处理,有如下三种操作

    时间的显示

    时间的转换

    时间的运算

    通常有这几种方式来表示时间

    1. 时间戳

    2. 格式化的时间字符串  如2019-09-22

    3. 元祖(9个元素)即struct_time

    time.time()  返回当前时间的时间戳

    import  time
    print(time.time()) #返回当前时间的时间戳
    
    time.localtime() 将一个时间戳转换为当前时区struct_time(元祖)
    import  time
    print(time.localtime()) 
    

    time.gmtime() 跟time.localtime()相似,将一个时间戳转换为UTC时区的struct_time(元祖)

    print(time.localtime())
    print(time.gmtime())
    <<<
    D:py_lisedaydayvenvScriptspython.exe D:/py_lise/dayday/第四章节/test1.py
    time.struct_time(tm_year=2019, tm_mon=9, tm_mday=22, tm_hour=23, tm_min=13, tm_sec=4, tm_wday=6, tm_yday=265, tm_isdst=0)
    time.struct_time(tm_year=2019, tm_mon=9, tm_mday=22, tm_hour=15, tm_min=13, tm_sec=4, tm_wday=6, tm_yday=265, tm_isdst=0)

    time.mktime   将一个struct_time(元祖)转换为时间戳

    print(time.mktime(time.localtime()))
    >>>
    1569165404.0
    

    time.sleep(secs)  线程推迟指定的时间运行

    time.sleep(5)
    print("----------------")

    time.asctime(t) 把一个表示时间的元祖或者struct_time表示为这种形式:Sun Sep 22 23:24:19 2019v,如果没有参数,将会将time.locatime()作为参数参入

    print(time.asctime())
    <<<
    Sun Sep 22 23:24:19 2019
    

    time.strftime()   把一个代表时间的元祖或者struct_time转化为格式化的时间字符串

    t1=time.strftime("%Y-%m-%d")
    print(t1)

    time.strptime()  把一个格式化的时间字符串转化为struct_time,和time.strftime() 向逆

    print(time.strptime("2020-3-10" ,"%Y-%m-%d"))
    print(time.strptime("2020-3-10 19:30","%Y-%m-%d  %H:%M"))

    datetime模块

     datetime模块定义了下面这些类:

    datetime.date:表示日期的类,常用的属性有year,month,day

    >>> datetime.date.today()
    datetime.date(2020, 3, 10)
    >>>

    datetime.datetime:表示日期时间

    1. d=datetime.datetime.now() 返回当前的datetime日期类型
    >>> datetime.datetime.now()
    datetime.datetime(2020, 3, 10, 20, 0, 7, 276440)
    >>>

    datetime.timedelta:表示时间间隔,即两个时间点之间的长度

    时间运算

    >>> datetime.datetime.now()
    datetime.datetime(2020, 3, 10, 20, 8, 29, 194335)
    >>> datetime.datetime.now()+datetime.timedelta(4)
    datetime.datetime(2020, 3, 14, 20, 9, 15, 596157)
    >>>
    >>> datetime.datetime.now()+datetime.timedelta(hours=3)
    datetime.datetime(2020, 3, 10, 23, 10, 33, 309874)
    >>>

    random 随机数模块

    验证码

    命名规范:random_mod.py

    1.random.randrange   >>返回1-10之间的一个随机数,不包括10

    import random
    random.randint(1,10)

    2.random.randint(1,10)  >>返回1-10之间的一个随机数,包括10

    >>> random.randint(1,10)
    9
    >>>

    3. random.randrange(0,100,2)   随机选择0-100的偶数

    import random
    
    print(random.randrange(0,100,2))
    

    4.random.rangdom()   返回一个随机浮点数

    import random
    
    print(random.random())
    

    5.random.choice()返回一个给定数据集合中的随机字符

    import random
    
    print(random.choice('avfsdd$98'))
    

    6.random.sample()  从多个字符中选取特定数量的字符

    import random
    
    print(random.sample('avfsdd$98',3))
    

    string       生成随机字符串

    1.  string.ascii_lowercase  返回有序的小写字符

    import string
    
    print(string.ascii_lowercase)
    

    2.string.digits

    import string
    
    print(string.ascii_lowercase)
    print(string.digits)
    

    生成随机字符串

    import string
    import random
    a=string.ascii_lowercase+string.digits
    print(a)
    b=random.sample(a,5)
    print("".join(b))
    

    洗牌

    import string
    import random
    a=string.digits
    print(a)
    b=list(a)
    print(b)
    random.shuffle(b)
    print(b) 

    序列化pick&json模块

    import pickle
    d = {'k1':'v1','k2':'v2'}
    f_dumps = pickle.dumps(d) #序列化
    d_dumps = pickle.loads(f_dumps) #反序列化
    print(d_dumps)
    f = open("game.pkl","wb")
    pickle.dump(d,f)
    import  pickle
    
    f = open("game.pkl","rb")
    d1=pickle.load(f)
    print(d1)
    

    dump  写入文件

    dumps  生成序列化的字符串

    load  从文件加载

    loads  把序列化的字符串反向解析  

    json    VS      pickle

    import json
    d = {'k1':'v1','k2':'v2'}
    json_1 = json.dumps(d)
    print(json_1)
    print(type(json_1))
    

    输入:

    {"k1": "v1", "k2": "v2"}
    <class 'str'>

    import json
    d = {'k1':'v1','k2':'v2'}
    # json_1 = json.dumps(d)
    # print(json_1)
    # print(type(json_1))
    f = open("json.json","w")
    json_2 = json.dump(d,f)
    print(json_2)
    

     

    import json
    f = open("json.json","r")
    json_3 = json.load(f)
    print(json_3)
    

    区别 

    json:

    支持所有语言

    只支持常规的数据类型,str,int,  dict,  list  ,tuple

    pickle:

    只支持python

    支持python里所有的数据类型

    hashlib  加密

    散列

    hash碰撞

    两个不同的输入,转化成相同的输出

    在当前进程下,hash出的值是唯一,如果退出则变掉了

     加密算法在hash的基础上加工而成的

    MD5

    可以产生128位的散列值

    特点“

    1、压缩性

    2、容易计算

    3、抗修改性

    4、强抗碰撞

    MD5 不可逆

    MD5的用途

    1、防止篡改

    2、防止看到明文

    3、防止抵赖(数字签名)

    SHA-1

    安全hash算法

    160位

    升级SHA-256

    文件copy模块shutil

    正则表达式

     字符串的匹配规则,

    .     默认匹配除 之外的任意一个字符,

    >>> re.search(".","abcddd")
    <re.Match object; span=(0, 1), match='a'>
    >>>
    

    ^  匹配字符开头

    >>> re.search("^a","abcddd")
    <re.Match object; span=(0, 1), match='a'>
    >>> re.search("^abc","abcddd")
    <re.Match object; span=(0, 3), match='abc'>
    >>>
    

     $  匹配字符结尾

    >>> re.search("abc$","abcdddabc")
    <re.Match object; span=(6, 9), match='abc'>
    >>>
    

     * 匹配*号前的字符0次或多次

    >>> re.search("a*","aaaaaaaaaaaaaabcabcdddabc")
    <re.Match object; span=(0, 14), match='aaaaaaaaaaaaaa'>
    >>>
    

     +  匹配前一个字符1次或多次

    >>> re.findall("aa+","aa9900888")
    ['aa']
    >>> re.findall("aa+","aaaaaaa9900888")
    ['aaaaaaa']
    >>> re.findall("aa+","aaaaaaa9900888aaa")
    ['aaaaaaa', 'aaa']
    >>> re.findall("aa+","aaaaaaa990088aaa8aaa")
    ['aaaaaaa', 'aaa', 'aaa']
    >>>
    

    ?  匹配前一个字符1次或0次

    >>> re.search("a?","aaaaaaaaaaaaaabcabcdddabc")
    <re.Match object; span=(0, 1), match='a'>
    >>>
    

     {m}  匹配前一个字符m次

    >>> re.search('b{3}','alexbbbs').group()
    'bbb'
    >>>
    

     {n,m}   匹配一个字符n到m次

    >>> re.findall('b{2,3}','bbalbbbbexbbbs')
    ['bb', 'bbb', 'bbb']
    >>>
    

    | 匹配左或右的字符

    >>> re.search('b|a','alexbbbs').group()
    'a'
    >>> re.search('b|a','balexbbbs').group()
    'b'
    >>>
    

    (……) 分组匹配,

    >>> re.search("(abc){2}a(123|45)", "abcabca456c").group()
    'abcabca45'
    >>>

    A  只从字符开头匹配

    >>> re.search('Aa','abalexbbbs')
    <re.Match object; span=(0, 1), match='a'>
    >>>

       匹配字符结尾  同$

    >>> re.search('a','balexbbbsa')
    <re.Match object; span=(9, 10), match='a'>
    >>>

    d  匹配数字0-9  且只匹配一次

    >>> re.search('d','balexbb89999')
    <re.Match object; span=(7, 8), match='8'>
    >>>

    D  匹配非数字  且只匹配一次

    >>> re.search('D','balexbb89999')
    <re.Match object; span=(0, 1), match='b'>
    >>>

    w  匹配【A-Za-z0-9】  只匹配一次

    >>> re.search('w','balexbb89999')
    <re.Match object; span=(0, 1), match='b'>
    >>> re.search('w','9balexbb89999')
    <re.Match object; span=(0, 1), match='9'>
    >>>
    

    W    匹配非【A-Za-z0-9】  只匹配一次

    >>> re.search('W','9balexbb89999****')
    <re.Match object; span=(13, 14), match='*'>
    >>>  

    s    匹配空白字符、 、 、   只匹配一下

    >>> re.search("s+","ab	c1
    3").group()
    '	'
    >>> re.search("s+","ab
    c1
    3").group()
    '
    '
    >>> 

    (?P……)  分组匹配

    re的匹配语法有一下几种

    re.match  从头开始匹配

    re.search   匹配包含

    re.findall   把所有匹配到的字符放到以列表中的元素返回

    re.split  以匹配到的字符当作列表分隔符

    re.sub   匹配字符并替换

    re.fullmatch   全部匹配

    re.fullmatch

    (pattern,string,flags=0)

    pattern   正则表达式

    string   要匹配的字符串

    flags  标志位,用于控制正则表达式的匹配方式

     目录结构:

    包&跨目录导入

    一个文件夹管理多个模块文件,

    一个包就是一个文件夹,该文件下必须存在init.py

     在主目录下,建一个入口文件 manage.py【有了入口文件,就是意味着程序从包的根目录开始导入,也就是可以跨目录调用了】

    入口文件里面调用view模块,

    然后view文件里面去调用settings模块

    如下:

     views调用settings

    LOGING日志模块

    日志级别:

    从低到高:debug,info,watning,error,critial

    1.把日志写到文件里

    import logging
    #debug,info,watning,error,critial
    logging.basicConfig(filename="log.log",level=logging.INFO)
    logging.debug("user[alex]attempted wrong more than 3 times")
    logging.info("server is down")
    logging.warning("log is log")

    输出结果:

    新增一个文件,文件内容为:
    INFO:root:server is down
    WARNING:root:log is log

    解释:

    level=logging.INFO,也就是说只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子, 第一条日志是不会被纪录的,如果希望纪录debug的日志,那把日志级别改成DEBUG就行了。

    自定义日志格式

    import logging
    logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
    logging.warning('log is log.')
    

     输出

    03/14/2020 08:11:41 PM log is log.

    所有支持的格式

    %(name)s   Logger的名字

    %(levelname)s 文本形式的日志格式

    %(pathname)s 调用日志输出函数的模块的完整路径名,

    %(filename)s  调用日志输出函数的模块的文件名

    %(module)s  调用日志输出函数的模块名

    %(funcName)s  调用日志输出函数的函数名

    %(lineno)d 调用日志输出函数的语句所在的代码行

    %(created)f  当前时间,用UNIX标准的表示时间浮点数表示

    %(relativeGreated)d   输出日志信息时的,自Logger创建以来的毫秒数

    %(asctime)s  字符串时间的当前时间,默认格式是2003-07-05  08:26:45,888  逗号后面的是毫秒

    %(thread)d  线程ID

    %(threadName)s  线程名

    %(process)d 进程ID

    %(message)s  用户输出的消息

    日志同时输出到屏幕和文件

    logger  提供了应用程序可以直接使用的接口

    handler  将logger创建的日志记录发送到合适的目的输出

    filter  提供了 细度设备来决定输出哪条日志记录

    formatter  决定日志记录的最终输出格式

    Logger

    每个程序输出信息之前都要活得一个Logger

    LOG=logging.getLogger("")
    

     还可以绑定handler   filter

    Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高
    Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
    Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler
    

     可以设置日志级别:

    Logger.debug()、

    Logger.info()、

    Logger.warning()、

    Logger.error()、

    Logger.critical()

    Handler

    Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
    Handler.setFormatter():给这个handler选择一个格式
    Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象

    每个Logger可以附件多个Handler

    logging.StreamHandler  可以向文件对象输出信息
    logging.FileHandler 同StreamHandler类似,不过它可以打开文件

    logging.handlers.RotatingFileHandler 管理文件大小,如果超过某个大小值,也会重新生成一个,

    logging.handlers.TimedRotatingFileHandler   同RotatingFileHandler类似,间隔一定时间就 自动创建新的日志文件

    formatter组件

    可以和handler组合

    日志级别:

    全局的日志级别默认为warning

    全局设置为debug   屏幕设置为info,如果输出的日志界别为debug,那么屏幕就不会打印

    import logging
    #1.生成Logger对象
    logger = logging.getLogger("mysql")
    logger.setLevel(logging.DEBUG)
    #logger.setLevel()
    #logger.addFilter()
    #logger.removeFilter()
    #logger.addHandler()
    #logger.removeHandler()
    #2.生成handler对象
    cn=logging.StreamHandler()
    fn= logging.FileHandler("mysql.log")
    cn.setLevel(logging.INFO)
    #handler.setLevel()
    #handler.addFilter()
    #handler.removeFilter()
    #2.1 把handler对象绑定Logger
    logger.addHandler(fn)
    logger.addHandler(cn)
    
    #3.生成formatter对象
    fn_formatter=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    cn_formater=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    #3.1把formatter对象绑定handler
    fn.setFormatter(fn_formatter)
    cn.setFormatter(cn_formater)
    logger.debug("test log 1")
    logger.info("test log 2")
    logger.warning("test log 3 ")
    

      

  • 相关阅读:
    六种简单易理解的排序算法
    leetcode-數組篇
    leetcode-字符串篇
    java8 Optional优雅非空判断
    md2all 简单实用
    zooleeper面试题
    深入理解 JVM锁 与 分布式锁
    redission 高性能分布式锁
    Java传统 定时任务
    关于Zookeeper
  • 原文地址:https://www.cnblogs.com/hantongxue/p/11295213.html
Copyright © 2011-2022 走看看