python “名称空间和作用域” 以及 “模块的导入和使用”
七、名称空间和作用域
可以简单理解为存放变量名和变量值之间绑定关系的地方。
1、名称空间
在 Python 中有各种各样的名称空间:
-
全局名称空间:每个程序的主要部分定义了全局的变量名和变量值的对应关系,这样就叫做全局名称空间
-
局部名称空间:在函数的运行中定义的临时的空间叫做局部名称空间,只可以被这个函数所有。函数运行结束后,这个局部的名称空间就会销毁。
-
内置名称空间:内置名称空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。
1、三种名称空间之间的加载顺序
python3 test.py # 1、python解释器先启动,因而首先加载的是:内置名称空间 # 2、执行test.py文件,然后以文件为基础,加载全局名称空间 # 3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
2、名字的查找顺序
当我们要使用一个变量时,先从哪里找?
局部使用:局部名称空间——>全局名称空间——>内置名称空间
x = 1 def f1():x = 10print(x) f1() # 输出 10
全局使用:全局——>内置
#需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例 x = 1 def f1():x = 10print(x) print(x) # 输出 1
2、作用域
作用域就是变量名的生效范围
分为: 全局作用域 和 局部作用域
1、全局作用域
内置的名称空间中的名字和全局名称空间的名字属于这个全局作用域。
-
全局作用域中的名字,在整个文件的任意位置都能被引用,全局存活,全局内都有效。
2、局部作用域
局部名称空间的名字属于局部作用域。
-
局部作用域中的名字只能在其本地局部生效和使用。
-
python
中局部作用域就是函数内定义或生成的名字,临时存活,随着函数调用的结束而消失。
八、模块的导入和使用
1、模块介绍
-
Python 有时候称为胶水语言,就是因为它有强大的可扩展性,这个扩展性就是用模块实现的。
-
模块其实就是一个以
.py
结尾的 Python 文件,这个文件中可以包含变量、函数、类等。 -
模块可以包含实现了一个或者多个功能的代码。
-
模块可以在其他 Python 文件中使用,可以通过网络进行传播。
这样的话,如果想在你的程序中实现某些功能,其实网络的其他程序猿已经给你写好了,下载下来,安装到自己的环境下,就可以使用了。
2、为什么要模块化
模块化编程是指将大型,笨拙的编程任务分解为单独的,更小的,更易于管理的子任务或模块的过程。然后可以像构建块一样拼凑单个模块以创建更大的应用程序。
在大型应用程序中模块化代码有几个优点:
-
简单性:模块通常只关注问题的一小部分,而不是关注当前的整个问题。如果您正在处理单个模块,那么您的头脑中要思考的将有一个较小的问题范围。这使得开发更容易,更不容易出错。
-
可维护性:模块通常设计为能够在不同的问题域之间实施逻辑边界。如果以最小化相互依赖性的方式编写模块,则对单个模块的修改将对程序的其他部分产生影响的可能性降低。(您甚至可以在不了解该模块之外的应用程序的情况下对模块进行更改。)这使得许多程序员团队在大型应用程序上协同工作更加可行。
-
可重用性:单个模块中定义的功能可以通过应用程序的其他部分轻松地重用。这消除了重新创建重复代码的需要。
-
范围:模块通常定义一个单独的命名空间,这有助于避免程序的不同区域中的变量名之间的冲突。
函数,模块和包都是Python中用于促进代码模块化的构造。
3、模块的分类
1、实现方式分类
实际上有两种不同的方法可以在Python中定义模块:
-
模块可以用Python本身编写。
-
模块可以用C编写并在运行时动态加载,就像
re
(正则表达式)模块一样。
以上两种情况下,模块的内容都以相同的方式访问:使用import
语句
2、模块的归属分类
-
-
包含在解释中的一个内置的模块本,像
[itertools](https://realpython.com/python-itertools/)
模块。
-
-
-
其他机构或个人开发者编写的模块,成为第三方模块
-
-
-
自己写的
.py
文件,就是自定义的模块
-
3、第三方模块
从网络上下载的模块称为 第三方模块。
安装方法
1、 pip3
工具安装
例如下面的示例是安装用于执行远程主机命令的模块 paramiko
注意: pip3 是 bash 环境下的命令 pip3 install paramiko
python2.x 使用
pip
python3.x 使用pip3
当然这也不是固定的,比如你给pip3
定义了一个别名pip
2、源码安装
源码安装就是,从网络上下载没有封装的 python 文件的源码,之后在本地执行其源码中的 setup.py
文件进行安装。
模块的源码一般都有一个主目录,主目录中包含了一个到多个子目录和文件。 但是主目录下一定有一个 setup.py
的文件,这个是源码安装的入口文件,就是需要执行这个文件并且传入一个 install
参数进行源码安装。
示例:
a. 下载源码包
wget https://files.pythonhosted.org/packages/4a/1b/9b40393630954b54a4182ca65a9cf80b41803108fcae435ffd6af57af5ae/redis-3.0.1.tar.gz
b. 解压源码包
tar -xf redis-3.0.1.tar.gz
-
进入模块源码的主目录,并安装源码包
上面表示安装成功
4、自定义模块
有的情况下,是需要自己编写一些模块的,这种就是自定义模块了。
示例:
some_mod.py x = 10 li = ['shark', 18] def foo():return 30 class Person():def __init__(self, name, age):self.name = nameself.age = age
5、内置模块
模块除了 第三方模块, 自定义模块,还有 内置模块。
4、模块的使用
-
使用模块需要先导入模块名。
-
模块名就是把
.py
去掉后的文件名。比如some_mod.py
的模块名就是some_mod
1、导入模块
import some_mod
2、使用模块中的对象
要想使用模块中的变量名或者函数名等,只需要使用 模块名.变量名
的方式即可。
例如,下面是使用的了 some_mod
模块中的 foo
函数。
import some_mod some_mod.foo()
3、更多模块导入的方式
a. 从模块中导入其中的一个对象
from some_mod import x
b. 从模块中导入多个对象
from some_mod import x, foo
c. 从模块中导入全部的对象, 不建议这么做
from some_mod import *
4、导入模块时模块的代码会自动被执行一次
st = """www.qfecu.com 千峰欢迎您! www.qfecu.com 千峰欢迎您! """ print(st)
5、模块名的搜索路径
当你导入模块或者包的时候, 查找模块或包的顺序:
-
系统会先从当前目录下查找
-
之后再从
sys.path
输出的值中的路径里查找模块名或者包名。
import sys print(sys.path)
sys.path
输出的值是一个 Python 的列表,这个列表我们可以对其修改的。
比如我们可以把某个文件的路径添加到此列表中,通常会这么做。
run.py import os import sys BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # python2 sys.path.insert(0, BASE_DIR) sys.path.insert(0,'D:\gitlab') # 将D:\gitlab 添加到python解释器的查询列表中 print(sys.path)
九、常用模块
1、sys 模块
提供了一系列有关Python运行环境的变量和函数
#python3 sys模块 #sys模块负责程序与python解释器的交互,提供了一系列的函数和变量, #用于操控python运行时的环境。 !# sys.argv 接收命令行参数,生成一个List,第一个元素是程序本身路径 # sys.modules.keys() 返回所有已经导入的模块列表 # sys.exc_info() 获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息 !# sys.exit(n) 退出程序,正常退出时exit(0) # sys.hexversion 获取Python解释程序的版本值,16进制格式如:0x020403F0 # sys.version 获取Python解释程序的版本信息 # sys.maxsize 获取内存中最大的Int值 python2中是maxint # sys.maxunicode 获取内存从中最大的Unicode值 # sys.modules 返回系统导入的模块字典,key是模块名,value是模块 !# sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 !# sys.platform 返回操作系统平台名称 # sys.stdout 标准输出 # sys.stdin 标准输入 # sys.stderr 错误输出 !# sys.exec_prefix 返回平台独立的python文件安装的位置 # sys.byteorder 本地字节规则的指示器,big-endian平台的值是'big',little-endian平台的值是'little' # sys.copyright 记录python版权相关的东西 # sys.api_version 解释器的C的API版本 import sys sys.argv # 命令行参数列表,第一个元素是程序本身路径;用于接收执行# Python 脚本时传的参数 # 示例: python3 echo.py a b c # echo.py 文件内容 import sys print(sys.argv[1:]) # 输出结果 ['a', 'b', 'c'] print('脚本名称:{}'.format(sys.argv[0])) for i in sys.argv:if i == sys.argv[0]:continueprint('参数为:',i)print('总参数个数:{}'.format(len(sys.argv)-1)[root@python python]# ./sysargv.py s1 s2 s3 s4 s5 脚本名称:./sysargv.py 参数为: s1 参数为: s2 参数为: s3 参数为: s4 参数为: s5 总参数个数:5
2、os 模块
os模块是与操作系统交互的一个接口,包含普遍的操作系统功能,如果你希望你的程序能够与平台有关的话,这个模块是尤为重要的。
import os # os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 # pwd # os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd # cd # os.curdir 返回当前目录: ('.') # os.pardir 获取当前目录的父目录字符串名:('..') # os.makedirs('dirname1/dirname2') 可生成多层递归目录 # mkdir -p # os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 rmdir -p # os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname # mkdir # os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname # rmdir # os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 # ls -A # os.remove() 删除一个文件 # rm -f # os.rename("oldname","newname") 重命名文件/目录 rename mv # os.stat('path/filename') 获取文件/目录信息 # os.sep 输出操作系统特定的路径分隔符,win下为"\",Linux下为"/" # os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n" # os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为: # os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' # os.system("bash command") 运行shell命令,直接显示 #一般用于脚本中去打印 # 这种方法实用性不如 os.popen subprocess.getoutput # os.environ 获取系统环境变量 # os.path.abspath(path) 返回path规范化的绝对路径 # os.path.split(path) 将path分割成目录和文件名二元组返回 # 不去检测文件系统 # os.path.dirname(path) 返回path的上一层目录。其实就是os.path.split(path)的第一个元素 # os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 # os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False # if [ -e ] # os.path.isabs(path) 如果path是绝对路径,返回True # os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False # if [ -f ] # os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False # if [ -d ] # os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,最后一个绝对路径之前的参数将被忽略 # os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 # os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 开始练习 import os # 获取当前工作目录,即当前python脚本工作的目录路径 os.getcwd() # 切换当前脚本工作目录;相当于shell下cd os.chdir("./dirname") # 创建单级目录,相当于 shell 中的 mkdir dirname os.mkdir('dirname') # 递归创建目录 os.makedirs('dir1/dir2') # 删除单级空目录,若目录非空则无法删除,并报错。 os.rmdir('dirname') # 递归删除 空 目录 os.removedirs('dir1/dir2') # 列出指定目录下的所有文件和目录,包括隐藏文件,并以列表方式打印 os.listdir('dirname') # 递归查找目录下的文件和目录,返回一个生成器对象。 # 生成器对象是个可迭代对象,每一层包含了三个值: # 1. 当前目录路径,2. 其下面的所有子目录, 3. 其下面的所有文件 os.walk('dirname') ### 练习需求 ### 1. 在 /tmp 目录下,创建目录 a/b/c 2. 进入到 /tmp/a/b 目录下,创建一个目录 f 3. 把当前的工作目录写到 f 目录下的 work.txt 文件内。 4. 删除目录 c 5. 把 /tmp 目录下及其子目录下的所有文件和目录打印到屏幕上 # 如果path存在,返回True;如果path不存在,返回False 在这里值得注意的是, # 在Linux shell 中,Python会认为: / 左边一定是一个目录,而不是文件 os.path.exists(path) # 如果path是一个存在的目录,则返回True。否则返回False os.path.isdir(path) # 如果path是一个存在的文件,返回True。否则返回False os.path.isfile(path) # 删除一个文件 os.remove('file') # 重命名文件/目录 os.rename("oldname", "new") # 如果path是绝对路径,返回 True os.path.isabs(path) # 将 path 分割成目录和文件名二元组返回 os.path.split(path) # 返回 文件 或 path 规范化的绝对路径 os.path.abspath(path) # 返回path的目录。 其实返回的就是 os.path.split(path) 的第一个元素 os.path.dirname(path)# 将多个路径组合后返回,每个路径之间不需要加路径分隔符(\或者/) os.path.join(path1[, path2[, ...]])
3、time 时间模块
1、time 模块
在Python中,通常有这几种方式来表示时间:
-
时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始到目前的秒数。我们运行
type(time.time())
,返回的是float类型。 -
结构化的时间(struct_time):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,周几,一年中第几天,夏令时)
属性 值 tm_year(年) 比如2011 tm_mon(月) 1 - 12 tm_mday(日) 1 - 31 tm_hour(时) 0 - 23 tm_min(分) 0 - 59 tm_sec(秒) 0 - 61(60和61为闰秒) tm_wday(weekday) 0 - 6(0表示周一) tm_yday(一年中的第几天) 1 - 366 tm_isdst(是否是夏令时) 默认为 0
-
格式化的时间字符串(Format String)
# 快速认识它们 In [139]: import time In [140]: time.time() Out[140]: 1522057206.0065496 In [141]: time.localtime() # 本地时间, 结构化时间 Out[141]: time.struct_time(tm_year=2018, tm_mon=3, tm_mday=26, tm_hour=17, tm_min=40, tm_sec=53, tm_wday=0, tm_yday=85, tm_isdst=0) In [142]: time.gmtime() # 格林威治时间(UTC) Out[142]: time.struct_time(tm_year=2018, tm_mon=3, tm_mday=26, tm_hour=9, tm_min=43, tm_sec=31, tm_wday=0, tm_yday=85, tm_isdst=0) In [143]: time.strftime("%Y-%m-%d %X") Out[143]: '2018-03-26 17:40:40' #time模块没有time.py文件,是内置到解释器中的模块 #三种时间表示方式 ''' 1、时间戳(timestamp): 通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。 2、格式化的时间字符串:"2018-09-03 10:02:01" 3、元组(struct_time):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时) ''' #UTC:(Coordinated Universal Time,世界协调时),亦即格林威治天文时间,世界标准时间。在中国为UTC+8 #DST:(Daylight Saving Time),即夏令时。 大家开始练习 import time #时间戳 time() print(time.time()) 1535939025.4159343 #struct_time localtime([secs]) 将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。 #当地时间 print(time.localtime(time.time())) time.struct_time(tm_year=2018, tm_mon=9, tm_mday=3, tm_hour=9, tm_min=46, tm_sec=7, tm_wday=0, tm_yday=246, tm_isdst=0) print(time.localtime()) time.struct_time(tm_year=2018, tm_mon=9, tm_mday=3, tm_hour=9, tm_min=48, tm_sec=19, tm_wday=0, tm_yday=246, tm_isdst=0) t_local=time.localtime() print(t_local.tm_year) print(t_local.tm_mon) print(t_local.tm_mday) #gmtime([secs]) 将一个时间戳转换为UTC时区(0时区)的struct_time。 print(time.gmtime()) time.struct_time(tm_year=2018, tm_mon=9, tm_mday=3, tm_hour=1, tm_min=51, tm_sec=38, tm_wday=0, tm_yday=246, tm_isdst=0) mktime(t) : 将一个struct_time转化为时间戳。 print(time.mktime(time.localtime())) 1535939934.0 asctime([t]) : 把一个表示时间struct_time表示为这种形式:'Mon Sep 3 10:01:46 2018'。默认将time.localtime()作为参数传入。 print(time.asctime()) Mon Sep 3 10:01:46 2018 ctime([secs]) : 把一个时间戳转化为time.asctime()的形式,默认time.time()为参数。 print(time.ctime()) Mon Sep 3 10:05:40 2018 strftime(format[, t]) # 把一个代表时间的struct_time转化为格式化的时间字符串。 # 如果t未指定,将传入time.localtime()。 # 如果元组中任何一个元素越界,ValueError的错误将会被抛出。 print(time.strftime("%Y-%m-%d %X")) #%X 等同于 %H%M%S print(time.strftime("%Y-%m-%d %X",time.localtime())) print(time.strftime("%Y-%m-%d %H:%M:%S")) strptime(string[, format]) # 把一个格式化时间字符串转化为struct_time。实际上它是strftime()是逆操作。 print(time.strptime('2018-09-03 10:14:53', '%Y-%m-%d %X')) time.struct_time(tm_year=2018, tm_mon=9, tm_mday=3, tm_hour=10, tm_min=14, tm_sec=53, tm_wday=0, tm_yday=246, tm_isdst=-1) sleep(secs) time.sleep(10) #停止10秒,继续运行
格式化时间的变量:
格式 | 含义 |
---|---|
%a | 本地(locale)简化星期名称 |
%A | 本地完整星期名称 |
%b | 本地简化月份名称 |
%B | 本地完整月份名称 |
%c | 本地相应的日期和时间表示 |
%d | 一个月中的第几天(01 - 31) |
%H | 一天中的第几个小时(24小时制,00 - 23) |
%I | 第几个小时(12小时制,01 - 12) |
%j | 一年中的第几天(001 - 366) |
%m | 月份(01 - 12) |
%M | 分钟数(00 - 59) |
%p | 本地am或者pm的相应符 |
%S | 秒(00 - 61) |
%U | 一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周。 |
%w | 一个星期中的第几天(0 - 6,0是星期天) |
%W | 和%U基本相同,不同的是%W以星期一为一个星期的开始。 |
%x | 本地相应日期 |
%X | 本地相应时间 |
%y | 去掉世纪的年份(00 - 99) |
%Y | 完整的年份 |
%Z | 时区的名字(如果不存在为空字符) |
%% | ‘%’字符 |
2、时间的互相转换
In [153]: time.time() Out[153]: 1522071229.4780636In [154]: time.localtime(1522071229.4780636)In [155]: time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(1522071229.4780636))In [156]: time.strptime('2018-03-26 21:41', "%Y-%m-%d %H:%M")In [157]: time.mktime(time.localtime()) In [178]: time.ctime(1093849081) Out[178]: 'Mon Aug 30 14:58:01 2004'In [179]: time.asctime(time.localtime()) Out[179]: 'Mon Mar 26 21:49:41 2018'In [183]: time.strptime('Mon mar 04 21:53:42 2018') In [182]: time.strptime('Mon mar 04 21:53:42 2018', "%a %b %d %H:%M:%S %Y") time.sleep(5) # 休眠 5 秒钟 print(time.clock()) # 精确到毫秒
3、datetime 模块
datetame 是 time 的升级版
import datetime In [192]: str(datetime.date.fromtimestamp(time.time())) Out[192]: '2018-03-26' In [193]: str(datetime.datetime.now()) Out[193]: '2018-03-26 22:09:44.424473' In [194]: datetime.datetime.now() + datetime.timedelta(3) Out[194]: datetime.datetime(2018, 3, 29, 22, 10, 42, 315584) In [196]: datetime.datetime.now() + datetime.timedelta(minutes=30) Out[196]: datetime.datetime(2018, 3, 26, 22, 41, 32, 44547) In [15]: datetime.date.strftime(datetime.datetime.now(),'%Y-%m') Out[15]: '2018-04'In [16]: datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m') Out[16]: '2018-04' import time,datetime print('返回当前时间:',datetime.datetime.now()) 显示结果: 返回当前时间: 2017-12-19 18:13:01.974500 print('时间戳直接转成字符串格式: ',datetime.date.fromtimestamp(time.time())) 显示结果: 时间戳直接转成字符串格式: 2017-12-19 print('当前时间精确到微秒:',datetime.datetime.now()) 显示结果: 当前时间精确到微妙: 2017-12-19 18:13:01.974500 print('当前时间+3天: ',datetime.datetime.now() + datetime.timedelta(3)) 显示结果: 当前时间+3天: 2017-12-22 18:13:01.974500 print('当前时间-3天',datetime.datetime.now() + datetime.timedelta(-3)) 显示结果: 当前时间-3天 2017-12-16 18:13:01.974500print('当前时间+3小时',datetime.datetime.now() + datetime.timedelta(hours=3)) 显示结果: 当前时间+3小时 2017-12-19 21:13:01.974500 print('当前时间+30分: ',datetime.datetime.now() + datetime.timedelta(minutes=30)) 显示结果: 当前时间+30分: 2017-12-19 18:43:01.974500 print('当前时间+2年:',datetime.datetime.now()+datetime.timedelta(days=365*2)) 显示结果: 当前时间+2年: 2019-12-19 18:13:01.974500 c_time = datetime.datetime.now() print('时间替换:', c_time.replace(minute=3,hour=2)) #时间替换 显示结果: 时间替换: 2017-12-19 02:03:01.974500
4、shutil 压缩打包模块
shutil 是 Python3 中高级的文件 文件夹 压缩包 处理模块
1、拷贝文件
拷贝文件的内容到另一个文件中,参数是文件的相对路径或者绝对路径
import shutil shutil.copyfile('./src.file','./dst.file') #给目标文件命名
2、拷贝文件和权限
import shutil shutil.copy2('f1.log', 'f2.log')
3、递归拷贝
递归的去拷贝文件夹
shutil.copytree(src, dst, symlinks=False, ignore=None)
shutil.copytree('/home','/tmp/hbak',ignore=shutil.ignore_patterns('*.txt')) # 递归拷贝一个文件夹下的所有内容到另一个目录下,目标目录应该是原来系统中不存在的
shutil.ignore_patterns(*patterns) 忽略某些文件
ignore=shutil.ignore_patterns('排除的文件名', '排除的文件夹名') 支持通配符,假如有多个用逗号隔开
4、递归删除
递归删除一个文件夹下的所有内容
shutil.rmtree('/tmp/hb') shutil.rmtree('/tmp/hbad/') # 最后结尾的一定是明确的文件名,不可以类似下面这样 shutil.rmtree('/tmp/hbak/*')
5、递归移动
递归的去移动文件,它类似mv命令。
shutil.move('/home/src.file', './shark')
6、压缩
创建压缩包并返回文件路径,例如:zip、tar
# 将 /home/shark 目录下的所以文件打包压缩到当前目录下, # 名字 shark,格式 gztar。扩展名会自动根据格式自动生成。 shutil.make_archive('shark', # 压缩后文件名'gztar', # 指定的压缩格式'/home/shark/') # 被压缩的文件夹名字 # 将 /home/shark 目录下的所以文件打包压缩到 /tmp 目录下,名字shark,格式 tar shutil.make_archive( '/tmp/shark','tar','/home/shark/') # 查看当前 python 环境下支持的压缩格式 ret = shutil.get_archive_formats() print(ret)
7、解压缩
# 解压的文件名 解压到哪个路径下,压缩的格式 shutil.unpack_archive('./a/b.tar.gz', './a/c/','gztar')
5、subprocess 模块执行本机系统命令
os.system()
执行的命令只是把命令的结果输出导终端,程序中无法拿到执行命令的结果。
subprocess
是开启一个系统底层的单个进程,执行 shell 命令,可以得到命令的执行结果。
# 在 shell 中运行命令,并且获取到标准正确输出、标准错误输出 In [209]: subprocess.getoutput('ls |grep t') Out[209]: 'test.py' In [222]: ret = subprocess.getstatusoutput('date -u') In [223]: ret Out[223]: (0, '2018年 03月 26日 星期一 14:46:42 UTC')
6、Python3 正则模块(标准库)
1、常用特殊字符匹配内容
字符匹配:
正则特殊字符 | 匹配内容 |
---|---|
. | 匹配除换行符(\n)以外的单个任意字符 |
\w | 匹配单个字母、数字、汉字或下划线 |
\s | 匹配单个任意的空白符 |
\d | 匹配单个数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配整个字符串的开头 |
$ | 匹配整个字符串的结尾 |
次数匹配:
正则特殊字符 | 匹配内容 |
---|---|
* | 重复前一个字符 0 - n 次 |
+ | 重复前一个字符 1 - n 次 |
? | 重复前一个字符 0 - 1 次 |
{n} | 重复前一个字符 n 次 a{2} |
匹配 aa | |
{n,} | 重复前一个字符 n 次或 n 次以上 a{2,} |
匹配 aa | |
或aaa | |
以上 | |
{n, m} | 重复前一个字符 n 到 m 次之间的任意一个都可以 |
2、Python 中使用正则的方法
match
只在整个字符串的起始位置进行匹配
示例字符串
string = "isinstance yangge enumerate www.qfedu.com 1997"
示例演示:
import re In [4]: r = re.match("is\w+", string) In [8]: r.group() # 获取匹配成功的结果 Out[8]: 'isinstance'
search
从整个字符串的开头找到最后,当第一个匹配成功后,就不再继续匹配。
In [9]: r = re.search("a\w+", string) In [10]: r.group() Out[10]: 'ance'
findall
搜索整个字符串,找到所有匹配成功的字符串, 把这些字符串放在一个列表中返回。
In [16]: r = re.findall("a\w+", string) In [17]: r Out[17]: ['ance', 'angge', 'ate']
sub
把匹配成功的字符串,进行替换。
re.sub的功能 re是regular expression的缩写,表示正则表达式;sub是substitude的缩写,表示替换 re.sub是正则表达式的函数,实现比普通字符串更强大的替换功能 # 语法: """ ("a\w+", "100", string, 2) 匹配规则,替换成的新内容, 被搜索的对象, 有相同的替换次数 """ sub(pattern,repl,string,count=0,flag=0) 1、pattern正则表达式的字符串 eg中r'\w+' 2、repl被替换的内容 eg中'10' 3、string正则表达式匹配的内容eg中"xy 15 rt 3e,gep" 4、count:由于正则表达式匹配的结果是多个,使用count来限定替换的个数从左向右,默认值是0,替换所有的匹配到的结果eg中2 5、flags是匹配模式,可以使用按位或者“|”表示同时生效,也可以在正则表达式字符串中指定 eg: In [24]: import re In [24]: re.sub(r'\w+','10',"xy 15 rt 3e,gep",2,flags=re.I ) '10 10 rt 3e,gep', 其中r'\w+'为正则表达式,匹配多个英文单词或者数字,'10'为被替换的内容,“xy 15 rt 3e,gep”是re匹配的字符串内容,count只替换前2个,flag表示忽略大小写 In [24]: r = re.sub("a\w+", "100", string, 2)In [25]: r Out[25]: 'isinst100 y100 enumera www.qfedu.com 1997' # 模式不匹配时,返回原来的值
split
以匹配到的字符进行分割,返回分割后的列表
re.split(pattern, string, maxsplit=0, flags=0) pattern compile 生成的正则表达式对象,或者自定义也可 string 要匹配的字符串 maxsplit 指定最大分割次数,不指定将全部分割 flags 标志位参数 (了解) re.I(re.IGNORECASE) 使匹配对大小写不敏感 re.L(re.LOCAL) 做本地化识别(locale-aware)匹配 re.M(re.MULTILINE) 多行匹配,影响 ^ 和 $ re.S(re.DOTALL) 使 . 匹配包括换行在内的所有字符 re.U(re.UNICODE) 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. re.X(re.VERBOSE) 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
In [26]: string Out[26]: 'isinstance yangge enumerate www.qfedu.com 1997' In [27]: r = re.split("a", string, 1)
使用多个界定符分割字符串
>>> line = 'asdf fjdk; afed, fjek,asdf, foo' >>> import re >>> re.split(r'[;,\s]\s*', line) ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
3、正则分组
从已经成功匹配的内容中,再去把想要的取出来
# match In [64]: string Out[64]: 'isinstance yangge enumerate www.qfedu.com 1997' In [65]: r = re.match("is(\w+)", string) In [66]: r.group() Out[66]: 'isinstance' In [67]: r.groups() Out[67]: ('instance',)In [68]: r = re.match("is(in)(\w+)", string))In [69]: r.groups() Out[69]: ('in', 'stance') # search # 命名分组 In [87]: r = re.search("is\w+\s(?P<name>y\w+e)", string) In [88]: r.group() Out[88]: 'isinstance yangge' In [89]: r.groups() Out[89]: ('yangge',) 6 In [90]: r.groupdict() Out[90]: {'name': 'yangge'} 8 # findall In [98]: string Out[98]: 'isinstance all yangge any enumerate www.qfedu.com 1997' In [99]: r = re.findall("a(?P<name>\w+)", string) In [100]: r Out[100]: ['nce', 'll', 'ngge', 'ny', 'te'] In [101]: r = re.findall("a(\w+)", string) In [102]: r Out[102]: ['nce', 'll', 'ngge', 'ny', 'te'] # split In [113]: string Out[113]: 'isinstance all yangge any enumerate www.qfedu.com 1997' In [114]: r = re.split("(any)", string) In [115]: r Out[115]: ['isinstance all yangge ', 'any', ' enumerate www.qfedu.com 1997'] In [116]: r = re.split("(a(ny))", string) In [117]: r Out[117]: ['isinstance all yangge ','any','ny',' enumerate www.qfedu.com 1997'] In [118]: tag = 'value="1997/07/01"' In [119]: s = re.sub(r'(value="\d{4})/(\d{2})/(\d{2}")', r'\1-\2-\3', tag) In [120]: s Out [120]: value="1997-07-01"
编译正则
对于程序频繁使用的表达式,编译这些表达式会更有效。
compile 函数用于编译正则表达式,返回的是一个正则表达式( Pattern )对象,利用这个对象的相关方法再去匹配字符串。
好处:
re 模块会维护已编译表达式的一个缓存。
不过,这个缓存的大小是有限的,直接使用已编译的表达式可以避免缓存查找开销。
使用已编译表达式的另一个好处是,通过在加载模块时预编译所有表达式,可以把编译工作转到应用 一开始时,而不是当程序响应一个用户动作时才进行编译。
In [130]: regexes = re.compile("y\w+") In [131]: r = regexes.search(string) In [132]: r.group() Out[132]: 'yangge'
常用正则
# IP: r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b" # 手机号: r'\b1[3|4|5|6|7|8|9][0-9]\d{8}' # 邮箱: shark123@qq.com shark123@163.com r'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+'
强调知识点
# 匹配所有包含小数在内的数字 print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3'] #.*默认为贪婪匹配 print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b'] #.*?为非贪婪匹配:推荐使用 print(re.findall('a.*?b','a1b22222222b')) #['a1b']
元字符
# \b 表示匹配单词边界,详见后面的速查表 In [17]: re.search('hello\b', 'hello world') In [18]: re.search('hello\\b', 'hello world') Out[18]: <_sre.SRE_Match object; span=(0, 5), match='hello'>
Python 自己也有转义
使用 r 禁止 Python 转义
In [19]: re.search(r'hello\b', 'hello world') Out[19]: <_sre.SRE_Match object; span=(0, 5), match='hello'>
扩展知识点
最后一个参数 flag
可选值有:
re.I # 忽略大小写
示例:
In [186]: s1 = string.capitalize() In [187]: s1 Out[187]: 'Isinstance all yangge any enumerate www.qfedu.com 1997' In [192]: r = re.search('is',s, re.I) Out[192]: <_sre.SRE_Match object; span=(0, 2), match='Is'>
4、正则模式速查表
模式 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[...] | 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k' |
[^...] | 不在[]中的字符:abc 匹配除了a,b,c之外的字符。 |
re* | 匹配0个或多个的表达式。 |
re+ | 匹配1个或多个的表达式。 |
re? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{n,m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a| b | 匹配a或b |
(re) | 匹配括号内的表达式,也表示一个组 |
\w | 匹配字母数字及下划线 |
\W | 匹配非字母数字及下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]. |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。 |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\n, \t, 等. | 匹配一个换行符。匹配一个制表符。等 |
\1...\9 | 匹配第n个分组的内容。 |
\10 | 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。 |
7、Python3 邮件模块
使用第三方库 **yagmail**
更新: 第三种方式的隐藏用户名和密码的方式,目前不再支持
1、简单介绍 yagmail
目标是尽可能简单,无痛地发送电子邮件。
最终的代码如下:
import yagmail yag = yagmail.SMTP() contents = ['This is the body, and here is just text http://somedomain/image.png','You can find an audio file attached.', '/local/path/song.mp3'] yag.send('to@someone.com', '邮件标题', contents)
或者在一行中实现:
yagmail.SMTP('mygmailusername').send('to@someone.com', 'subject', 'This is the body')
当然, 以上操作需要从你自己系统的密钥环中读取你的邮箱账户和对应的密码。关于密钥环稍后会提到如何实现。
2、安装模块
pip3 install yagmail # linux / Mac pip install yagmail # windows
这样会安装最新的版本,并且会支持所有最新功能,主要是支持从密钥环中获取到邮箱的账户和密码。
3、关于账户和密码
开通自己邮箱的 **SMTP**
** 功能,并获取到授权码**
这个账户是你要使用此邮箱发送邮件的账户,密码不是平时登录邮箱的密码,而是开通 POP3/SMTP
功能后设置的客户端授权密码。
这里以 126
邮箱为例:
4、方式一:不使用系统的密钥环
不使用系统的密钥环,可以直接暴露账户和密码在脚本里
import yagmail yag = yagmail.SMTP(user='自己的账号',password='账号的授权码',host='smtp.qq.com', # 邮局的 smtp 地址port='端口号', # 邮局的 smtp 端口smtp_ssl=False) yag.send(to='收件箱账号',subject='邮件主题',contents='邮件内容')
5、方式二: 使用系统的密钥环管理账户和授权码
模块支持从当前系统环境中的密钥环中获取账户和密码,要想实现这个功能,需要依赖模块 keyring
。之后把账户和密码注册到系统的密钥环中即可实现。
1. 安装依赖模块
pip3 install keyring # CentOS7.3 还需要安装下面的模块 pip3 install keyrings.alt
2. 开始向密钥环注册
import yagmail yagmail.register('你的账号', '你的授权密码')
注册账户和密码,只需要执行一次即可。
3. 发送邮件
import yagmail yag = yagmail.SMTP('自己的账号',host='smtp.qq.com', # 邮局的 smtp 地址port='端口号', # 邮局的 smtp 端口smtp_ssl=False # 不使用加密传输 ) yag.send(to='收件箱账号',subject='邮件主题',contents='邮件内容')
6、示例展示
下面是以我的 126 邮箱为例, 使用系统密钥环的方式,向我的 163邮箱发送了一封邮件。
import yagmail yag = yagmail.SMTP(user='shark@126.com',host='smtp.126.com',port=25,smtp_ssl=False) yag.send(to='docker@163.com',subject='from shark',contents='test')
这样就愉快的发送了一封测试邮件到 docker@163.com
的邮箱。
当然前提是:
-
126 邮箱开通了
SMTP
功能。 -
把 126 邮箱的账号和密码已经注册到自己系统的密钥环中。
7、发送附件
发送
发送附件只需要给 send
方法传递 attachments
关键字参数
比如我在系统的某一个目录下有一张图片,需要发送给 docker@163.com
import yagmail yag = yagmail.SMTP(user='shark@126.com',host='smtp.126.com',port=25,smtp_ssl=False) yag.send(to='docker@163.com',subject='from shark',contents='test',attachments='./松鼠.jpeg')
8、收到的邮件和附件
image.png
9、使用 ssl
发送加密邮件
要发送加密邮件,只需要把 smtp_ssl
关键字参数去掉即可,因为默认就是采用的加密方式 smtp_ssl=True
。
不传递 stmp_ssl
关键字参数的同时,需要设置端口为邮箱服务提供商的加密端口,这里还是以 126 邮箱为例,端口是 465
。
import yagmail yag = yagmail.SMTP(user='shark@126.com',host='smtp.126.com',port=465) yag.send(to='docker@163.com',subject='from sharkyunops',contents='test',attachments='./松鼠.jpeg')
10、发送 带 html 标记语言的邮件内容
在实际的生产环境中,经常会发送邮件沟通相关事宜,往往会有表格之类的内容,但是又不想以附件的形式发送,就可以利用 html 标记语言的方式组织数据。
import yagmail yag = yagmail.SMTP(user='shark@126.com',host='smtp.126.com',port=465) html="""<table border="1"><thead><tr><th>姓名</th><th>年龄</th></tr></thead><tbody><tr><td>shak</td><td>18</td></tr><tr><td>西瓜甜</td><td>28</td></tr></tbody> </table> """ yag.send(to='docker@163.com',subject='from sharkyunops',contents=['test',html])
11、更多
如果不指定to
参数,则发送给自己
如果to
参数是一个列表,则将该邮件发送给列表中的所有用户
attachments
参数的值可以是列表,表示发送多个附件
8、Python3 paramiko 模块
Paramiko 模块提供了基于ssh连接,进行远程登录服务器执行命令和上传下载文件的功能。这是一个第三方的软件包,使用之前需要安装。
1、安装
pip3 install paramiko
2、执行命令
1、基于用户名和密码的连接
封装 Transport
import paramiko #实例化一个transport(传输)对象 transport = paramiko.Transport(('172.16.32.129',2323)) #建立连接 transport.connect(username='root',password='123') #建立ssh对象 ssh = paramiko.SSHClient() #绑定transport到ssh对象 ssh._transport=transport #执行命令 stdin,stdout,stderr=ssh.exec_command('df') #打印输出 print(stdout.read().decode()) #关闭连接 transport.close() import paramiko transport = paramiko.Transport(('172.16.153.134', 22)) transport.connect(username='root', password='upsa') ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df -P') print(stdout.read().decode()) transport.close()
3、文件上传下载
SFTPClient:
用于连接远程服务器并进行上传下载功能。
下面的命令可以快速创建密钥对,并用 -t 指定了算法类型为 ecdsa
ssh-keygen -t ecdsa -N "" ssh-keygen ssh-copy-id 192.168.95.154
1、基于用户名密码上传下载
import paramiko transport = paramiko.Transport(('10.18.46.104',22)) transport.connect(username='root',password='123.com') #paramiko.SSHClient() sftp = paramiko.SFTPClient.from_transport(transport) # 将ssh-key.py 上传至服务器 /tmp/ssh-key.py sftp.put('ssh-key.py', '/tmp/ssh-key.txt') # 后面指定文件名称 # 将远程主机的文件 /tmp/ssh-key.py 下载到本地并命名为 ssh-key.txt sftp.get('/tmp/ssh-key.py', 'ssh-key.txt') transport.close()
相关文章:

python “名称空间和作用域” 以及 “模块的导入和使用”
七、名称空间和作用域 可以简单理解为存放变量名和变量值之间绑定关系的地方。 1、名称空间 在 Python 中有各种各样的名称空间: 全局名称空间:每个程序的主要部分定义了全局的变量名和变量值的对应关系,这样就叫做全局名称空间 局部名称…...

Pycharm导入自定义模块报红
文章目录 Pycharm导入自定义模块报红1.问题描述2.解决办法 Pycharm导入自定义模块报红 1.问题描述 Pycharm 导入自定义模块报红,出现红色下划线。 2.解决办法 打开【File】->【Setting】->【Build,Execution,Deployment】->【Console】->【Python Con…...

LLMs之KG-RAG:KG-RAG(基于知识图谱的RAG系统)的简介(可以解决多跳问题/同时支持结构化和非结构化数据查询)、经验技巧、案例应用之详细攻略
LLMs之KG-RAG:KG-RAG(基于知识图谱的RAG系统)的简介(可以解决多跳问题/同时支持结构化和非结构化数据查询)、经验技巧、案例应用之详细攻略 背景痛点:传统的基于向量相似度检索的RAG模型回答多环(多步)问题的能力有限,无法同时处理来自多个文…...

综合模型及应用(图论学习总结部分内容)
文章目录 前言六、综合模型及应用(以题目总结为主)分层图思想(包括拆点建图) e g 1 : 通信线路 eg1:通信线路 eg1:通信线路[A-Telephone Lines](https://ac.nowcoder.com/acm/contest/1055/A)(蓝书例题) e g 2 : 小雨坐地铁 eg2:小雨坐地铁 eg2:小雨坐地铁 [1012-小雨坐…...

2025考研专业课、英语、数学、政治视频大全,整理全了!
考研季又到了,备考的小伙伴们,你们准备好了吗? 时间管理 考研是一场与时间的赛跑,合理安排时间,让复习更高效! - 制定详细的学习计划,每天、每周、每月都有明确目标 - ♂️ 保持一定的学习…...
设计模式之策略模式(一)
背景: 下单时有很多情况,有的是用户下单,有的是卡密下单,有的是下游下单,有的是需要唤起支付,有的不需要支付,这样就需要写很多下单接口,下面使用策略模式优化这种情况 代码结构 com.example.order ├── controller │ └── OrderController.java ├── service │ …...
常见网络攻击及解决方案
网络安全是开发中常常会遇到的情况,为什么会遇到网络攻击,网络攻击是如何进行的,如何抵御网络攻击,都是我们需要思考的问题。 为什么会遇到网络攻击? 以下是一些主要的因素: 技术漏洞:软件或操…...

【挑战30天首通《谷粒商城》】-【第一天】【10 番外篇】 解决docker 仓库无法访问 + MobaXterm连接VirtualBox虚拟机
文章目录 课程介绍 1、解决docker 仓库无法访问 2、 MobaXterm连接VirtualBox虚拟机 Stage 1:下载MobaXterm选择适合你的版本 Stage 2:vagrant ssh 连接,开启ssh访问 Stage 2-1:su获取root账号权限,输入密码(默认vagra…...

【C++】每日一题 17 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 可以使用回溯法来解决这个问题。首先定义一个映射关系将数字与字母对应起来…...
vue预览PDF文件的几种方法
1.使用iframe标签预览PDF文件 1.1页面结构 html <iframe:src"fileUrl"id"iframeBox"ref"iframeRef"frameborder"0"style"width: 100%; height: 800px"></iframe>1.2 js代码 export default {data() {return {…...

深度学习入门到放弃系列 - 阿里云人工智能平台PAI部署开源大模型chatglm3
通过深度学习入门到放弃系列 - 魔搭社区完成开源大模型部署调用 ,大概掌握了开源模型的部署调用,但是魔搭社区有一个弊端,关闭实例后数据基本上就丢了,本地的电脑无法满足大模型的配置,就需要去租用一些高性价比的GPU机…...

GPT-4o,AI实时视频通话丝滑如人类,Plus功能免费可用
不开玩笑,电影《她》真的来了。 OpenAI最新旗舰大模型GPT-4o,不仅免费可用,能力更是横跨听、看、说,丝滑流畅毫无延迟,就像在打一个视频电话。 现场直播的效果更是炸裂: 它能感受到你的呼吸节奏…...

【优选算法】——Leetcode——202—— 快乐数
目录 1.题目 2. 题⽬分析: 3.简单证明: 4. 解法(快慢指针): 算法思路: 补充知识:如何求⼀个数n每个位置上的数字的平⽅和。 总结概括 5.代码实现 1.C语言 2.C 1.题目 202. 快乐数 编写一个算法来…...
华大基因CEPO-尹烨说学习与生活
怎么去面对生活和事业中的不确定性? 尹烨说,人类能够对抗不确定性的唯一的办法是,去让自己充电。 主持人问他,“和你同年的也有很多人,他们也可能也在学习,你怎么就能够脱颖而出呢?” 他说&am…...

C#中json数据序列化和反序列化的最简单方法(C#对象和字符串的相互转换)
文章目录 将C#对象转换为json字符串Newtonsoft模块的安装用Newtonsoft将对象转换为json字符串 将json字符串转换为C#对象 将C#对象转换为json字符串 本介绍将基于C#中的第三方库Newtonsoft进行,因此将分为Newtonsoft模块的安装和使用两部分。该模块的优势在于只需要…...
logback 日志脱敏
工具类 CustomLogbackPatternLayoutEncoder.java import ch.qos.logback.classic.encoder.PatternLayoutEncoder;public class CustomLogbackPatternLayoutEncoder extends PatternLayoutEncoder {/*** 正则替换规则*/private LogbackReplaces replaces;/*** 使用自定义 MyLog…...

element-ui的表单中,输入框、级联选择器的长度设置
使用<el-col>控制输入框的长度 <el-form-item label"姓名" label-width"80px"><el-col :span"15"><el-input v-model"form.name" autocomplete"off"></el-input></el-col></el-form…...

深入了解 npm:Node.js 包管理工具详解
文章目录 一、npm 基本概念1.1 什么是 npm?1.2 package.json 文件 二、npm 常用命令2.1 初始化项目2.2 安装依赖2.2.1 安装单个包2.2.2 全局安装包2.2.3 安装开发依赖 2.3 移除依赖2.4 更新依赖2.5 查看已安装的包2.6 发布包 三、npm 高级用法3.1 使用 npm scripts3…...

记一次跨域问题
线上跨域问题,在自己配置确认没问题下,要及时找运维看看是不是nginx配置问题。 两个方面: 项目代码 nginx配置 SpringBoot 解决跨域问题的 5 种方案! SpringBoot解决CORS跨域问题 SpringBoot-实现CORS跨域原理及解决方案...

第9章 负载均衡集群日常维护
一个设计良好的高可用负载均衡集群,交付使用以后并不能一劳永逸。欲使其高效、稳定、持续对外服务,日常维护必不可少。 对于高可用负载均衡集群来说,有两种类型的维护形式:常规性维护与突发性维护。突发性维护一般指故障处理&…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...