Python学习(六)---- 常用模块必备知识

原文地址:

https://blog.csdn.net/fgf00/article/details/52357477

编辑:智能算法,欢迎关注! 今天一起学习常见的模块,加油!


1. 模块介绍

1.1 定义

模块:本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test)

用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能)

1.2 语法

  • import 语句

当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。搜索路径是一个解释器会先进行搜索的所有目录的列表。

导入模块:

1import module1[, module2[,... moduleN]

调用符号:

1import os
2print(os.sep)
3print(os.getcwd())

Python的from语句让你从模块中导入一个指定的部分到当前命名空间中。语法如下:

1from modname import name1[, name2[, ... nameN]]

From…import* 语句

把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:

1from modname import *

这提供了一个简单的方法来导入一个模块中的所有项目。慎用 from…import *。

  • import 和 from 的区别

import导入使用时,加前缀 module.func()。相当于把模块代码放在当前文件中执行一遍。

from可以指定需要的函数或变量导入。

导入模块和当前py文件都有同一个函数,调用会调用哪一个?

因为python是解释型,所以后面覆盖前面。

  • import 本质

导入一个模块本质就是解释执行一个python文件

导入一个包本质就是解释该包下的__init__.py文件

1module = all_code(所有代码)
2import :本质把模块所有代码解释一遍,复制给模块名
3from module import name :把这个模块的代码把哪一部分给解释了,赋值给name
  • 包:__init__.py

包:本质就是一个目录(必须带有一个__init__.py文件),用来从逻辑上组织模块

导入包,怎么导入?

导入包的本质:执行包下面的__init__.py文件

导入包下的模块

包下面的模块,这样调用是错误的

1import package
2package.module.test()  # 这样调用是不行的。

在__init__.py内容中导入模块

1from . import module
2# "."指的相对路径,指的谁的相对路径?__init__.py的相对路径还是调用init的那个模块的?
3指的是__init__.py的相对路径。
  • 路径搜索和搜索路径

上面提到的都是导入同级目录下的模块,如果不在同一个目录下:

import module_name实际找module_name.py文件,是文件就一定要有路径。

导入模块就是:找到.py文件的位置,把它执行一遍,从哪里找呢?sys.path.

1>>> import sys
2>>> sys.path
3['', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python35\\python35.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python35\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python35\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python35', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python35\\lib\\site-packages']
1# 以上可见:sys.path 是一个列表,
2# 里面的 '' 指的当前路径,这是为何查找模块先从当前目录查找的原因
3os.path.abspath(__file__)  # 当前文件绝对路径
4os.path.dirname(os.path.abspath(__file__))  #获取目录名

加搜索路径

1sys.path.append() :追加到最后
2# 所以:可以如下,动态添加路径到第一位
3sys.path.insert 

1.3 导入优化

1import module_test
2# import导入情况,如果重复调用,python就会重复找,避免重复找,可以用from方式导入
3from module_test import test

果你不想让某个模块属性被 “from module import *” 导入 , 那么你可以给你不想导入的属性名称加上一个下划线( _ )。 不过如果你导入了整个模块或是你显式地导入某个属性这个隐藏数据的方法就不起作用了。

1.4 模块的分类

a:标准库

b:开源模块-第三方模块

c:自定义模块


2. 常用内置模块

2.1 os模块

用于提供系统级别的操作

 1os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
 2os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
 3os.curdir  返回当前目录: ('.')
 4os.pardir  获取当前目录的父目录字符串名:('..')
 5os.makedirs('dirname1/dirname2')    可生成多层递归目录
 6os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
 7os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
 8os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
 9os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
10os.remove()  删除一个文件
11os.rename("oldname","newname")  重命名文件/目录
12os.stat('path/filename')  获取文件/目录信息
13os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
14os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"os.pathsep    输出用于分割文件路径的字符串
15os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
16os.system("bash command")  运行shell命令,直接显示
17os.environ  获取系统环境变量
18os.path.abspath(path)  返回path规范化的绝对路径
19os.path.split(path)  将path分割成目录和文件名二元组返回,它仅仅是以 "PATH" 中最后一个 '/' 作为分隔符,分隔后,将索引为0的视为目录(路径),将索引为1的视为文件名
20os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
21os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
22os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
23os.path.isabs(path)  如果path是绝对路径,返回True
24os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
25os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
26os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
27os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
28os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间

2.2 time和datetime

在Python中,通常有这几种方式来表示时间:

  • 时间戳
  • 格式化的时间字符串
  • 元组(struct_time)共九个元素。

由于Python的time模块实现主要调用C库,所以各个平台可能有所不同。

UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。

时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。返回时间戳方式的函数主要有time(),clock()等。

元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有gmtime(),localtime(),strptime()。

 1time.time()  # 获取时间戳:当前时间减1970-1-1 00:00 ==> 秒
 2>>> time.localtime()  # 本地时间,元组方式(tm_isdst() 是否夏令时)
 3time.struct_time(tm_year=2016, tm_mon=8, tm_mday=29, tm_hour=0, tm_min=51, tm_sec=37, tm_wday=0, tm_yday=242, tm_isdst=0) 
 4
 5help(time)  # 模块帮助
 6>>> time.timezone  # 查看时区
 7-28800  # 28800/60秒/60分 = 8时 ==> utc --> 标准+8 
 8
 9time.sleep()  # 时间睡几秒
10time.gmtime()   # 不加时间戳,为国际标准时间
11time.localtime()   # 不加时间戳,本地时间
12# 加上则从1970年开始算。
  • 时间转为时间戳
1>>> x = time.localtime()
2>>> x
3time.struct_time(tm_year=2016, tm_mon=8, tm_mday=29, tm_hour=1, tm_min=0, tm_sec=8, tm_wday=0, tm_yday=242, tm_isdst=0)
4>>> time.mktime(x)
51472403608.0  
  • 格式化时间字符串
1>>> time.strftime("%Y-%m-%d %X",x)
2'2016-08-29 01:00:08'
3>>> time.strptime('2016-08-29 01:00:08',"%Y-%m-%d %X")
4time.struct_time(tm_year=2016, tm_mon=8, tm_mday=29, tm_hour=1, tm_min=0, tm_sec=8, tm_wday=0, tm_yday=242, tm_isdst=-1)
5
6strftime('格式',struct_time)  --> "格式化字符串"
7strptime("格式化字符串","格式") --> "struct_time"
  • 转化时间戳和元组到时间字符串
1>>> time.asctime(time.localtime())  # tuple -> string
2'Mon Aug 29 01:10:47 2016' 
3>>> time.ctime(888888888)  # seconds -> string
4'Tue Mar  3 09:34:48 1998' 
  • 时间加减
1import datetime
2
3datetime.datetime.now() # 返回 2016-08-19 12:47:03.941925
4datetime.date.fromtimestamp(time.time())  # 时间戳直接转成日期格式 2016-08-19
5
6datetime.datetime.now() + datetime.timedelta(3) # 当前时间+3天
7datetime.datetime.now() + datetime.timedelta(-3) # 当前时间-3天
8datetime.datetime.now() + datetime.timedelta(hours=3) # 当前时间+3小时
9datetime.datetime.now() + datetime.timedelta(minutes=30) # 当前时间+30分

2.3 random模块

 1random.random()  # 0~1之间的随机数
 2random.randint(1,3)  # [1,2,3]
 3random.randrange(3)  # [0,1,2]
 4
 5random.choice('hello')  # 传入序列随机字母
 6random.sample('hello',2)  # 随机两个字母
 7random.uniform(1,3)  # 1~3直接随机
 8a = [1,2,3,4,5]
 9random.shuffle(a)  # 洗牌,打乱
10
11import string
12"".join(random.sample(string.hexdigits,4))  # 随机4位验证码

2.4 sys模块

1sys.argv           命令行参数List,第一个元素是程序本身路径
2sys.exit(n)        退出程序,正常退出时exit(0)
3sys.version        获取Python解释程序的版本信息
4sys.maxint         最大的Int值
5sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6sys.platform       返回操作系统平台名称
7sys.stdout.write('please:')
8val = sys.stdin.readline()[:-1]

2.5 shutil模块

高级的 文件、文件夹、拷贝、压缩包等 处理模块

1shutil.copy 拷贝文件和权限
2shutil.copytree(src,dst) 目录拷贝
3shutil.move(src, dst)
4shutil.rmtree
5shutil.make_archive('')  压缩包
6shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的

2.6 ConfigParser

用于对特定的配置进行操作,当前模块的名称在 python 3.x 版本中变更为 configparser。

来看一个好多软件的常见文档格式如下

 1[DEFAULT]
 2ServerAliveInterval = 45
 3Compression = yes
 4CompressionLevel = 9
 5ForwardX11 = yes
 6
 7[bitbucket.org]
 8User = hg
 9
10[topsecret.server.com]
11Port = 50022
12ForwardX11 = no

如果想用python生成一个这样的文档怎么做呢?

  • 生成
 1import configparser
 2
 3config = configparser.ConfigParser()
 4config["DEFAULT"] = {'ServerAliveInterval': '45',
 5                      'Compression': 'yes',
 6                     'CompressionLevel': '9'}
 7
 8config['bitbucket.org'] = {}
 9config['bitbucket.org']['User'] = 'hg'
10config['topsecret.server.com'] = {}
11topsecret = config['topsecret.server.com']
12topsecret['Host Port'] = '50022'     # mutates the parser
13topsecret['ForwardX11'] = 'no'  # same here
14config['DEFAULT']['ForwardX11'] = 'yes'
15with open('example.ini', 'w') as configfile:
16   config.write(configfile)
  • 读取出来
 1>>> import configparser
 2>>> config = configparser.ConfigParser()
 3>>> config.sections()
 4[]
 5>>> config.read('example.ini')
 6['example.ini']
 7>>> config.sections()
 8['bitbucket.org', 'topsecret.server.com']
 9>>> 'bitbucket.org' in config
10True
11>>> config['bitbucket.org']['User']
12'hg'
13>>> config['DEFAULT']['Compression']
14'yes'
15>>> topsecret = config['topsecret.server.com']
16>>> topsecret['ForwardX11']
17'no'
18>>> for key in config['bitbucket.org']: print(key)
19...
20user
21compressionlevel
22serveraliveinterval
23compression
24forwardx11
25>>> config['bitbucket.org']['ForwardX11']
26'yes'
  • configparser增删改查语法
 1[section1]
 2k1 = v1
 3k2:v2
 4
 5[section2]
 6k1 = v1
 7
 8import ConfigParser
 9
10config = ConfigParser.ConfigParser()
11config.read('i.cfg')
12
13########## 读 ##########
14#secs = config.sections()
15#print secs
16#options = config.options('group2')
17#print options
18
19#item_list = config.items('group2')
20#print item_list
21
22#val = config.get('group1','key')
23#val = config.getint('group1','key')
24
25########## 改写 ##########
26#sec = config.remove_section('group1')
27#config.write(open('i.cfg', "w"))
28
29#sec = config.has_section('wupeiqi')
30#sec = config.add_section('wupeiqi')
31#config.write(open('i.cfg', "w"))
32
33
34#config.set('group2','k1',11111)
35#config.write(open('i.cfg', "w"))
36
37#config.remove_option('group2','age')
38#config.write(open('i.cfg', "w"))

2.7 hashlib模块

用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法,hash 加密都是bytes类型

1import hashlib
2
3m = hashlib.md5()
4m.update(b"Hello")
5m.update(b"It's me")  # 更新字符串为“HelloIt's me”
6
7print(m.digest()) #2进制格式hash
8print(m.hexdigest()) #16进制格式hash
 1import hashlib
 2
 3# ######## md5 ########
 4
 5hash = hashlib.md5()
 6hash.update('admin')
 7print(hash.hexdigest())
 8
 9# ######## sha1 ########
10hash = hashlib.sha1()
11hash.update('admin')
12print(hash.hexdigest())
13
14# ######## sha256 ########
15hash = hashlib.sha256()
16hash.update('admin')
17print(hash.hexdigest())
18
19# ######## sha384 ########
20hash = hashlib.sha384()
21hash.update('admin')
22print(hash.hexdigest())
23
24# ######## sha512 ########
25hash = hashlib.sha512()
26hash.update('admin')
27print(hash.hexdigest())

python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密

1import hmac
2h = hmac.new('wueiqi')
3h.update('hellowo')
4print h.hexdigest()

2.8 Subprocess模块

调用subprocess.run(…)是推荐的常用方法,在大多数情况下能满足需求,但如果你可能需要进行一些复杂的与系统的交互的话,你还可以用subprocess.Popen(),语法如下:

1p = subprocess.Popen("find / -size +1000000 -exec ls -shl {} \;",shell=True,stdout=subprocess.PIPE)
2print(p.stdout.read())

可用参数:

 1args:shell命令,可以是字符串或者序列类型(如:list,元组)
 2bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
 3stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
 4preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
 5close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。 
 6所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
 7shell:同上
 8cwd:用于设置子进程的当前目录
 9env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
10universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
11startupinfo与createionflags只在windows下有效 
12将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

终端输入的命令分为两种:

  • 输入即可得到输出,如:ifconfig
  • 输入进行某环境,依赖再输入,如:python

需要交互的命令示例

 1import subprocess
 2
 3obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 4obj.stdin.write('print 1 \n ')
 5obj.stdin.write('print 2 \n ')
 6obj.stdin.write('print 3 \n ')
 7obj.stdin.write('print 4 \n ')
 8
 9out_error_list = obj.communicate(timeout=10)
10print out_error_list

2.9 re-正则表达式模块

常用正则表达式符号

 1'.'     默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
 2'^'     匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
 3'$'     匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
 4'*'     匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
 5'+'     匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
 6'?'     匹配前一个字符1次或0次
 7'{m}'   匹配前一个字符m次
 8'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
 9'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
10'(...)' 分组匹配
1'\A'    只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
2'\Z'    匹配字符结尾,同'$'
3'\d'    匹配数字0-9
4'\D'    匹配非数字
5'\w'    匹配[A-Za-z0-9]
6'\W'    匹配非[A-Za-z0-9]
7'\s'    匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'

最常用的匹配语法

1re.match('匹配模式',"字符串")  # 从头开始匹配
2re.search('匹配模式',"字符串")  # 匹配包含,匹配一次
3re.findall('匹配模式',"字符串")  # 把所有匹配到的字符放到以列表中的元素返回
4
5re.splitall  # 以匹配到的字符当做列表分隔符
6p = re.compile(r'\d+')  # 以数字作为分隔符
7print p.split('one1two2three3four4')  # 分割字符串
8re.sub('格式','替换为','字符串','次数')  # 匹配字符并替换

分组匹配 和 group()、groups()、groupdict()

 1s = 'abc (72.5%) 123'
 2# 简单使用:result.group() 返回匹配值
 3>>> re.search('\w+\s',s).group()
 4'abc '
 5# 上面看不出分组匹配的力量,匹配出多个想要的值。用“()”括起来
 6>>> result = re.search('(\w+)\s\((.*)\)\s(\w+)',s)
 7>>> result.group()  # 即:result.group(0)
 8'abc (72.5%) 123'
 9>>> result.group(1)
10'abc'
11>>> result.group(2)
12'72.5%'
13>>> result.group(3)
14'123'
15# .groups()  # 结果返回'tuple'
16>>> result.groups()
17('abc', '72.5%', '123')
18# .groupdict()  # 结果返回'dict'
19>>> num = "371481199306143242"
20>>> res = re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})", num)
21>>> res.groupdict()
22{'province': '3714', 'birthday': '1993', 'city': '81'}

2.10 logging模块

python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical() 5个级别,下面我们看一下怎么用。

最简单用法

1import logging
2
3logging.warning("user [alex] attempted wrong password more than 3 times")
4logging.critical("server is down")
5
6#输出
7WARNING:root:user [alex] attempted wrong password more than 3 times
8CRITICAL:root:server is down

看一下这几个日志级别分别代表什么意思

如果想把日志写到文件里,也很简单

1import logging
2
3logging.basicConfig(filename='example.log',level=logging.INFO)
4logging.debug('This message should go to the log file')
5logging.info('So should this')
6logging.warning('And this, too')

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

1logging.basicConfig(filename='example.log',level=logging.INFO)

感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上!

1import logging
2logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
3logging.warning('is when this event was logged.')
4
5#输出
612/12/2010 11:46:36 AM is when this event was logged.

如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识 了

 1import logging
 2
 3#create logger
 4logger = logging.getLogger('TEST-LOG')
 5logger.setLevel(logging.DEBUG)
 6
 7
 8# create console handler and set level to debug
 9ch = logging.StreamHandler()
10ch.setLevel(logging.DEBUG)
11
12# create file handler and set level to warning
13fh = logging.FileHandler("access.log")
14fh.setLevel(logging.WARNING)
15# create formatter
16formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
17
18# add formatter to ch and fh
19ch.setFormatter(formatter)
20fh.setFormatter(formatter)
21
22# add ch and fh to logger
23logger.addHandler(ch)
24logger.addHandler(fh)
25
26# 'application' code
27logger.debug('debug message')
28logger.info('info message')
29logger.warn('warn message')
30logger.error('error message')
31logger.critical('critical message')

2.11 json和pickle数据序列化

str eval

数据序列化

1import json
2json.dumps(info_)
3json.loads(f.read())

json只能处理简单的,所有语言通用的,函数不能json序列化

1import pickle
2
3data = pickle.load(f)  # 等于以下
4data = pickle.loads(f.read())

pickle可以序列化python所有的数据类型

2.12 shelve 模块

shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式

 1import shelve
 2
 3d = shelve.open('shelve_test') #打开一个文件
 4
 5class Test(object):
 6    def __init__(self,n):
 7        self.n = n
 8
 9
10t = Test(123) 
11t2 = Test(123334)
12
13name = ["alex","rain","test"]
14d["test"] = name #持久化列表
15d["t1"] = t      #持久化类
16d["t2"] = t2
17
18d.close()

2.13 xml处理模块

xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,json之前的交换方式

参考文档:http://www.cnblogs.com/alex3714/articles/5161349.html

2.14 PyYAML模块

Python也可以很容易的处理ymal文档格式,只不过需要安装一个模块,参考文档:http://pyyaml.org/wiki/PyYAMLDocumentation


声明:本文系网络转载,版权归原作者所有。如涉及版权,请联系删除!

原文发布于微信公众号 - 智能算法(AI_Algorithm)

原文发表时间:2018-08-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Create Sun

基础拾遗------redis详解

前言   这篇文章和以往的基础拾遗有所不同,以前的介绍的都是c#基础,今天介绍的是redis。因为项目中一只在使用,我想现在大部分项目中都会用到nosql,缓存...

31650
来自专栏李家的小酒馆

Java面试基本知识

Java基本知识 基本知识 服务器:Tomcat 支持Servlet jsp JBoss 开源应用服务器 Apache:最广泛的http服务器,只支持静态网页 ...

33700
来自专栏开源优测

BeautifulSoup的使用

参考资料地址:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id28

13010
来自专栏云霄雨霁

Java虚拟机--内存模型

23450
来自专栏Java架构沉思录

一文理清Java内存区域

Java虚拟机在执行 Java 程序的过程中会把它管理的内存划分为若干个不同的数据区域。根据《Java 虚拟机规范》将 Java虚拟机所管理的内存分为以下几个运...

12020
来自专栏张首富-小白的成长历程

Linux-四剑客-find-awk-grep-sed解释----未完结版

find - search for files in a directory hierarchy 搜索目录层次结构中的文件 用来在指定目录下面查找文件或目录,任...

20430
来自专栏无题

Java并发编程:volatile关键字解析

我将一些最关键的要点和结论先做一下总结。如果要做细致的理解,通读全文还是很有必要的。 1.并发编程中三个原则: 原子性,可见性,有序性 2.先行发生原则: ...

44560
来自专栏北京马哥教育

ansible之playbook功能简述

playbooks剧本简介 playbooks是ansible更为强大的配置管理组件,实现基于文本文件编排执行的多个任务,且多次重复执行。其是使用YAML(Ye...

38650
来自专栏散尽浮华

linux运维中的命令梳理(三)

----------文本操作命令---------- sed命令:文本编辑工具 sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可...

27580
来自专栏TechBox

【iOS】运行时消息传递与转发机制前言(一)对象的消息传递机制 objc_msgSend()(二)消息转发流程参考文章

14140

扫码关注云+社区

领取腾讯云代金券