Python运维-文本处理、系统和文件信息监控、外部命令

本节主要目录如下:

一、文本处理

1.1、Python编码解码

1.2、文件操作

1.3、读写配置文件

1.4、解析XML文件

二、系统信息监控

2.1、监控CPU信息

2.2、监控内存信息

2.3、监控磁盘信息

2.4、监控网络信息

2.5、获取进程信息

2.6、实例:常见的实用方法

三、文件系统监控

3.1、实例

四、执行外部命令subprocess

4.1、subprocess.run()方法*

4.2、Popen类

4.3、其他方法


一、文本处理

日常运维工作都离不开文本,如日志分析、编码转换、ETL加工等。

1.1、Python编码解码

  • 计算机只处理二进制数据,如果要处理文本,就需要将文本转换为二进制数据,再由计算机进行处理
  • 文本转换为二进制数据就是编码,将二进制数据转换为文本就是解码
  • 编码和解码要按一定的规则进行,这个规则就是字符集

常见的中文编码

  • GB2312GB2312-80是中国国家标准简体中文字符集,共收录6763个汉字,同时收录了包括拉丁字母、希腊字母。日文平假名字母、俄语西里尔字母在内的682个字符
  • GBK即汉字内码扩展规范,共收入21886个汉字和图形符号
  • GB8030与GB2312-1980和GBK兼容,共收录汉字70244个,是一二四字节变长编码

可看出支持的汉字范围:GB18030>GBK>GB2312

世界所有语言统一到一套编码中,这套编码就是Unicode编码。Unicode编码使用两个字节(16位bit)表示一个字符,比较偏僻的字符需要使用4个字节。

几乎所有的系统、编程语言都默认支持Unicode。如果一段纯英文文本,Unicode会占用比ASCII码多一倍的空间!UTF编码将一个Unicode字符编码成1-6个字节,常用的英文字母被编译成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。UTF编码有三种:

  • UTF-8:使用1、2、3、4个字节表示所有符号,优先使用1个字节,若无法满足,则增加一个字节,最多4个字节 。英文占1个字节、欧洲语系占2个字节、东亚占3个字节,其他特殊字符占4个字节。
  • UTF-16:使用2、4个字节表示所有符号,优先使用2个字节,否则使用4个字节表示。
  • UTF-32:使用4个字节表示所有字符。

 # 汉字的“汉”,在UTF-8字符集中3个字节list("汉".encode("UTF-8"))# [230, 177, 137]

而英文无论采用哪种编码,都是一致的。如果使用纯英文编写代码,就基本不会遇到编码问题:

 print(list("a".encode("ascii")))# [97]print(list("a".encode("gbk")))# [97]print(list("a".encode("utf-8")))# [97]

Python语言的with...as...用

 with open("a.txt") as file:data = file.read()

默认编码可以通过sys.getdefaultencoding()来查看Python解释器会用的默认编码

 import sysprint(sys.getdefaultencoding())# utf-8

说明电脑上Python解释器默认使用的是UTF-8编码,如果不指定Python解释器以何种编码解码,则默认以UTF-8方式解码源文件,因此在保存代码源文件时确保以UTF-8编码保存。

1.2、文件操作

1.2.1、普通文件操作

Python文件操作只需要一个open函数返回一个文件句柄,无需导入任何模块。

 f=open("a.txt")     # 打开文件,得到一个文件句柄,并赋值给一个变量print(f.read())     # 打印读取文件的内容 f.close()           # 关闭文件

oepn函数:

 open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True, opener=None)

  • 参数file是一个文件名称的字符串,如果文件不在程序当前的路径下,就需要在前面加上相对路径或绝对路径
  • 参数mode是一个可选参数,指示打开文件的方式,若不指定,则默认以读文本的方式打开文件:

    字符串含义
    'r'的方式打开(默认)
    'w'的方式打开文件,会先清空文件
    'X'创建一个新文件,以写方式打开
    'a'以写的方式打开文件,如果文件已存在,就在文件最后位置追加内容
    'b'以二进制方式打开,可以和读写命令共用
    't'以文本方式(默认)
    '+'以读和写方式打开文件,用于更新文件
    'U'通用的换行模式(弃用)
  • buffering是一个可选的参数,buffering=0表示关闭缓冲区(仅在二进制方式打开可用),buffering=1表示选择缓冲区(仅在文本方式打开时可用);buffering大于1时,其值代表固定大小的块缓冲区的大小。当不指定该参数时:二进制文件使用固定大小的块缓冲区,文本文件使用行缓冲区。

注意:

  • 记得使用完毕后及时关闭文件,释放资源。推荐傻瓜式操作方式:使用with关键字来帮我们管理上下文,系统会自动为我们关闭文件和处理异常

     with open('a.txt','w') as f:f.write("hello world")
  • open()函数是操作系统打开文件,如果没有指定编码,那么以操作系统默认编码打开;Windos下是gbk,在Linux下使utf-8。

常见的文件操作方法:

名称功能
f.read()读取所有内容,光标移动到文件末尾
f.readline()读取一行内容,光标移动到第二行首部
f.readlines()读取每一行内容,存于列表中
f.write('1111\n222\n')针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8'))针对b模式的写,需要自己写换行符
f.writelines(['333\n','444\n'])文件模式
f.write([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')])b模式
f.readable()文件是否可读
f.writable()文件是否可写
f.closed文件是否关闭
f.encoding如果文件打开模式为b,则没有该属性
f.flush()立刻将文件内容从内存刷到硬盘

读取文件内位置的定位方法:

  • 通过read方法传输参数
  • 以字节为单位定位,如seek、tell等。
    • seek(x,0)表示从起始位置即文件首行首字符开始移动x个字符。
    • seek(x,1)表示从当前位置向后移动x个字符.
    • seek(-x,2)表示从文件的结尾向前移动x个字符。

# 基于seek实现类似Linux命令tail-f的功能import timewith open('tmp.txt','rb') as f:f.seek(0,2)         # 将光标移动至文件末尾while True:         # 实时显示文件新增加的内容line = f.read()if line:print(line.decode('utf-8'),end='')else:time.sleep(0,2) # 读取完毕后短暂的睡眠# 当tmp.txt追加新的内容时,新内容会被程序立即打印出来

1.2.2、大文件的读取

当文件较小时,我们可以一次性全部读入内存,对文件的内容做出任意修改,再保存至磁盘:

with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:data = read_f.read()	# 全部读入内存,如果文件很大,则会很卡data = data.replace('str1','str2')	# 在内存中完成修改write_f.write(data)	# 一次性写入新文件
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')

当文件很大时,如GB级的文本文件,我们需要用文件的可迭代方式将文件的内容逐行读入内存,在逐行写入新文件,最后使用新文件覆盖源文件。

with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:for line in read_f:	# 可迭代对象f逐行操作,防止内存溢出line=line.replace('str1','str2')write_f.write(line)
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')

处理大数据还有多种方法:

  1. 通过read(size)增加参数,指定读取的字节数。

    while True:block = f.read(1024)if not block:break
  2. 通过readline(),每次只读一行。

    while True:line = f.readline()if not line:break

file对象常用的参数:

函数功能
file.close()关闭文件。关闭后不能再进行读写操作
file.flush()刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件,而不是被动等待输出缓冲区写入
file.fileno()返回一个整型的文件描述符,可以用在如os模块的read方法等一些底层操作上
file.isatty()如果文件连接到一个终端设备,则返回True,否则False
file.next()返回文件下一行
file.read([size])从文件读取指定的字节数,如果为给定或为负,则读取所有
file.readline([size])读取整行,包括"\n"字符
file.readlines([sizeint])读取所有行并返回列表,若给定sizeint>0,则返回总和为sizeint字节的行,实际读取值的可能比sizeint大,因为要填充缓冲区
file.seek(offset[,whence])设置文件当前位置
file.tell()返回文件当前位置
file.truncate([size])根据size参数截取文件,size参数可选
file.write(str)将字符串写入文件,没有返回值
file.writelines(sequence)向文件写入一个序列字符串列表,如果需要换行,则加入每行的换行符

1.2.3、序列化和反序列化

  • 序列化:将数据结构或对象转换成二进制串的过程
  • 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或对象的过程

Python的pickle模块实现了基本的数据序列和反序列化。

# 序列化(将对象obj保存至文件中)。
pickle.dump(obj,file,[,protocal])# 反序列化(从文件中恢复对象,并重构为原来的Python对象)
x=pickle.load(file)

序列化实例:

import pickle# 使用pickle模块将数据对象保存到文件# 字符串
data0 = "hello world"
# 列表
data1 = list(range(20))[1::2]
# 元组
data2 = ("x","y","z")
# 字典
data3 = {"a":data0,"b":data1,"c":data2}print(data0)
print(data1)
print(data2)
print(data3)output = open("data.pk1","wb")# 使用默认的protocal
pickle.dump(data0,output)
pickle.dump(data1,output)
pickle.dump(data2,output)
pickle.dump(data3,output)
output.close()

反序列化演示:

import pickle# 使用pickle模块从文件中重构Python对象
pkl_file = open("data.pk1","rb")data0 = pickle.load(pkl_file)
data1 = pickle.load(pkl_file)
data2 = pickle.load(pkl_file)
data3 = pickle.load(pkl_file)print(data0)
print(data1)
print(data2)
print(data3)pkl_file.close()

1.3、读写配置文件

配置文件是供程序运行时读取配置信息的文件,用于将配置信息与程序分离

Python内置的配置文件解析器模块configparser类来解析基本的配置文件。

常见的pip配置文件如下:

[global]
index-url = https://pypi.doubanio.com/simple
trusted-host = pypi.doubanio.com

读取配置文件的信息的实例:

import configparser
config = configparser.ConfigParser()    # 实例化ConfigParser类
config.read(r"lesson/pip.ini")
print("遍历配置信息")
for section in config.sections():print(f"section is [{section}")for key in config[section]:print(f"key is [{key}],value is [{config[section][key]}]")  # 打印键和值print("通过键获取相对应的值:")
print(f"index-url is [{config['global']['index-url']}]")
print(f"trusted-host is [{config['global']['trusted-host']}]")# 上述代码通过实例化ConfigParser类读取配置文件,遍历配置文件中的section信息及键值信息,通过索引获取值信息。

相关信息写入配置文件实例:

import configparser
config = configparser.ConfigParser()config["DEFAULT"] = {"ServerAliveInterval":"45","Compression":"yes","CompressionLevel":"9"
}config["bitbucket.org"] = {}
config["bitbucket.org"]["User"] = "hg"config["topsecret.server.com"] = {}
topsecret = config["topsecret.server.com"]
topsecret["Port"] = "50022"
topsecret["ForwardX11"] = "no"config["DEFAULT"]["ForwaldX11"] = "yes"with open("example.ini","w") as configfile:config.write(configfile)
with open("example.ini","r") as f:print(f.read())

configparser模块的接口非常直接、明确。注意以下几点:

  • section名称是区分大小写的
  • section下的键值对中键是不区分大小写的,config["bitbucket.org"]在写入时会统一变成小写user保存在文件中
  • section下的键值对中的值是不区分类型的,都是字符串,具体使用时需要转换成想要的数据类型
  • section的名称是[DEFAULT]时,其他section的键值会继承[DEFAULT]的键值信息

1.4、解析XML文件*

XML的全称是eXtensible Markup Language,意为可扩展的标记语言,是一种用于标记电子文件使其具有结构性的标记语言。被设计用来传输和存储数据,例如:

<note><to>George</to><form>John</form><heading>Reminder</heading><body>Don't forget the meeting!</body>
</note>

Python有三种方法解析XML:SAX、DOM、ElementTree

1.4.1、SAX(simple API for XML)

SAX是一种基于事件驱动的API,使用时涉及两个部分:解析器事件处理器。解析器负责读取XML文件,并向事件处理器发送相应的事件。事件处理器对相应的事件做出相应,对数据做出处理。

  • 创建一个新的XMLReader对象,parser_list是可选参数,是解析器列表xml.sax.make_parser([parser_list])
  • 自定义事件处理器,继承ContentHandler类

ContenHandler类的方法:

名称功能
characters(content)从行开始,遇到标签之前,存在字符,content的值为这些字符串 从下一个标签,遇到下一个标签之前,存在字符,content的值为这些字符串
startDocument()文档启动时调用
endDocument()解析器到达文档结尾时调用
startElement(name,attrs)遇到XML开始标签时调用,name是标签的名字,attrs是标签属性值字典
endElement(name)遇到XML结束标签时调用

语法:

xml.sax.parse(xmlfile,contenthandler[,errorhandler])
# 参数说明:
xmlstring:xml字符串
contenthandler:必须是一个ContentHandler的对象
errorhandler:如果指定该参数,则errorhandler必须是一个SAXErrorHandler对象

解析XML的例子:首先有一个example.xml:

<?xml version="1.0" encoding="UTF-8"?>
<library><book id="1"><title>Book Title One</title><author>Author A</author><year>2021</year></book><book id="2"><title>Book Title Two</title><author>Author B</author><year>2022</year></book><!-- More books can be added here -->
</library>

解析代码实例:

import xml.saxclass MySAXHandler(xml.sax.ContentHandler):def __init__(self):self.current_data = ""def startElement(self, tag, attributes):print(f"Start Element: {tag}")def endElement(self, tag):print(f"End Element: {tag}")if tag == "title":print(f"Title: {self.current_data}")self.current_data = ""elif tag == "author":print(f"Author: {self.current_data}")self.current_data = ""elif tag == "year":print(f"Year: {self.current_data}")self.current_data = ""def characters(self, content):self.current_data += content.strip()# 创建SAX解析器
parser = xml.sax.make_parser()
# 将我们自定义的处理类注册到解析器
parser.setContentHandler(MySAXHandler())# 解析XML文档
parser.parse("example.xml")

SAX用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件,一次处理一个标签,无需事先全部读取整个XML文档,处理效率较高。适用场景:

  • 对大型文件进行处理
  • 只需要文件的部分内容,或者只需从文件中得到特定信息
  • 想建立自己的对象模型时

1.4.2、DOM(Document Object Model)

文件对象模型是W3C组织推荐的处理可扩展置标语言的标准编程接口。

实例:使用xml.dom.minidom解析xml文件

import xml.dom.minidom
from xml.dom.minidom import parse# 假设我们有一个XML字符串,也可以从文件中读取
xml_string = """
<?xml version="1.0" encoding="UTF-8"?>
<library><book id="1"><title>Book Title One</title><author>Author A</author><year>2021</year></book><book id="2"><title>Book Title Two</title><author>Author B</author><year>2022</year></book>
</library>
"""# 解析XML字符串
dom = xml.dom.minidom.parseString(xml_string)
# 文档方式:
dom = xml.dom.minidom.parse("example.xml")# 获取<library>元素
library = dom.documentElement# 遍历所有的<book>元素
for book in library.getElementsByTagName('book'):# 获取<book>的id属性book_id = book.getAttribute('id')# 获取并打印<title>元素的文本title = book.getElementsByTagName('title')[0].firstChild.data# 获取并打印<author>元素的文本author = book.getElementsByTagName('author')[0].firstChild.data# 获取并打印<year>元素的文本year = book.getElementsByTagName('year')[0].firstChild.data# 打印信息print(f"Book ID: {book_id}")print(f"Title: {title}")print(f"Author: {author}")print(f"Year: {year}")print()  # 打印空行以便区分每本书的信息# 代码使用minidom解析器打开文档,使用getElementsByTagName方法获取所有标签并遍历子标签,逻辑上比SAX直观

1.4.3、ElementTree

ElementTree将XML数据在内存中解析成,通过树来操作XML。

import xml.etree.ElementTree as ETtree = ET.parse("example.xml")
root = tree.getroot()
print(f"这是一个早餐菜单\n{root.attrib['year']}")for child in root:print("Book:",child[0].text)print("Title:",child[1].text)

二、系统信息监控

Python获取系统信息的模块是psutil(process and system utilities)。

2.1、监控CPU信息

import psutilpsutil.cpu_times()				# 获取CPU(逻辑CPU的平均)占用时间的详细信息
psutil.cpu_times(percpu=True)   # 获取每个CPU占用时间的详细信息
psutil.cpu_count()      		# CPU逻辑数量
psutil.cpu_count(logical=False) # CPU物理数量
psutil.cpu_percent()        	# CPU占比
psutil.cpu_percent()        	# 每个CPU的占比

2.2、监控内存信息

psutil.virtual_memory()     # 数值以字节为单位显示,自行转换

2.3、监控磁盘信息

psutil.disk_partitions()
psutil.disk_usage('/')      # 磁盘使用情况

2.4、监控网络信息

psutil.net_io_counters()    # 获取网络读写字节数/包的个数
psutil.net_if_addrs()       # 获取网络接口信息
psutil.net_if_stats()       # 获取网络接口状态
psutil.net_connections()    # 获取当前网络连接信息

2.5、获取进程信息

for pid in psutil.pids():	# 获取所有进程的pidprint(pid,end=',')
for proc in psutil.process_iter(attrs=['pid','name','username']):if proc.info['name'].startswith('Wechat'):	# 查找微信程序的相关信息print(proc.info)# psutil.process_iter返回的是一个可迭代对象,每个元素的info是一个字典,通过其可以获取我们关心的信息:
psutil.Process(12476).cpu_times()   # 获取CPU占用
psutil.Process(12476).memory_info() # 获取内存占用,rss就是实际占用的内存
psutil.Process(12476).num_threads() # 获取线程数
psutil.Process(12476).memory_percent()  # 获取内存占比

2.6、实例:常见的实用方法

import import os
import psutil
import signal# 按名称查找进程相关信息 1
def find_procs_by_name1(name):"Return a list of processes matching 'name'."ls = []for p in psutil.process_iter(attrs=['name']):if p.info['name'] == name:ls.append(p)return ls# 按名称查找进程相关信息 2
def find_procs_by_name2(name):ls = []for p in psutil.process_iter(attrs=["name","exe","cmdline"]):if name == p.info['name'] or \p.info['exe'] and os.path.basename(p.info['exe']) == name or \p.info['cmdline'] and p.info['cmdline'][0] == name:ls.append(p)return ls# 杀掉进程树
def kill_proc_tree(pid,sig=signal.SIGTERM,include_parent=True,timeout=None,on_terminate=None):if pid == os.getpid():raise RuntimeError("I refuse to kill myself")parent = psutil.Process(pid)children = parent.children(recursive=True)if include_parent:children.append(parent)for p in children:p.send_signal(sig)gone,alive = psutil.wait_procs(children,timeout=timeout,callback=on_terminate)return (gone,alive)# 杀掉子进程
def reap_children(tiemout=3):def on_terminate(proc):print("process {} terminated with exit code {}".format(proc,proc.returncode))procs = psutil.Process().children()# send SIGTERMfor p in procs:p.terminate()gone,alive = psutil.wait_procs(procs,timeout=tiemout,callback=on_terminate)if alive:# send SIGKILLfor p in alive:print("process {} survived SIGTERM;trying SIGKILL" % p)p.kill()gone,alive = psutil.wait_procs(alive,timeout=tiemout,callback=on_terminate)if alive:# give upfor p in alive:print("process {} survived SIGKILL;giving up" % p)

三、文件系统监控

如某个目录被删除,或者某个文件被修改、移动、删除时需要执行一定的操作或发出警报。Python使用watchdog库来实现文件系统监控,其原理是通过操作系统的事件触发

3.1、实例

import time
from watchdog.events import *
from watchdog.observers import Observerclass FileEventHandler(FileSystemEventHandler):def __init__(self):FileSystemEventHandler.__init__(self)def on_moved(self, event):now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())if event.is_directory:print(f"{now}文件夹由{event.src_path}移动至{event.dest_path}")else:print(f"{now}文件由{event.src_path}移动至{event.dest_path}")def on_created(self, event):now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())if event.is_directory:print(f"{now}文件夹{event.src_path} 创建")else:print(f"{now}文件{event.src_path} 创建")def on_deleted(self, event):now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())if event.is_directory:print(f"{now}文件夹{event.src_path} 删除")else:print(f"{now}文件{event.src_path} 删除")def on_modified(self, event):now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())if event.is_directory:print(f"{now}文件夹{event.src_path} 修改")else:print(f"{now}文件{event.src_path} 修改")if __name__ == '__main__':observer = Observer()path = r"d:/test"event_handler = FileEventHandler()observer.schedule(event_handler, path, True)  # True表示递归子目录print(f"监控目录{path}")observer.start()observer.join()

适用场景:

  • 监控文件系统中文件或目录的增、删、改情况
  • 当特定的文件被创建、删除、修改、移动时执行相应的任务

四、执行外部命令subprocess

subprocess是Python自带的模块,主要用来取代一些旧的模块或方法,如os.system等。适用subprocess模块更方便地执行操作系统支持的命令,可与其他应用程序结合适用

4.1、subprocess.run()方法*

这是官方推荐使用的方法,查看其原型:

subprocess.run(args,*,stdin=None,input=None,stdout=None,stderr=None,shell=False,cwd=None,timeout=None,check=False,encoding=None,errors=None)

该函数返回一个CompletedProcess类的实例,其常用参数:

  • args代表需要在操作系统中执行的命令。可以是字符串形式(要去shell=True),也可以是列表list类型
  • *代表可变参数,一般是列或字典形式
  • stdin、stdout、stderr指定了可执行程序的标准输入、标准输出、标准错误文件句柄。
  • shell代表程序是否需要在shell上执行
  • check设置为True表示检车命令的返回值,当返回值为非0时,就抛出CalledProcessError异常
  • timeout设置超时时间,如果超时,则强制kill掉子进程

在Linux系统中操作,实例自行查找

4.2、Popen类

Popen类的构造函数:

class subprocess.Popen(args,bufsize=-1, 	# 0无缓冲、1行缓冲,其他正值,缓冲区大小,负值,默认系统缓冲executable=None,# 一般不用stdin=None, 	# None没有任何重定向,继承父进程。PIPE创建管道...stdout=None,stderr=None,preexec_fn=None, 	# 钩子函数close_fds=True,		shell=False, cwd=None, env=None, universal_newlines=None,startupinfo=None, creationflags=0)

使用方法:

subprocess.Popen(["getit","abc.txt"])
subprocess.Popen("getit abc.txt")

Popen类的对象还有其他实用方法:

名称功能
poll()检查是否结束,设置返回值
wait()等待结束,设置返回值
communicate()参数是标准输入,返回标准输出和标准出错
send_signal()发送信号(主要在unix下有用)
terminate()终止进程,unix对应的SIGTERM信号,windows下调用api函数TerminateProcess()
kill()杀死进程(unix对应SIGKILL信号),windows同上
stdin stdout stderr参数中指定PIPE时,可以使用
pid进程ID
returncode进程返回值

4.3、其他方法

  • subprocess.call(*popenargs,**kwargs):call方法调用Popen()执行程序,并等待它完成
  • subprocess.check_call(*popenargs,**kwargs):调用前面的call(),如果返回值非0,则抛出异常
  • subprocess.check_output(*popenargs,**kwargs):调用Popen()执行程序,并返回其标准输出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/833286.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【知识点随笔分享 | 第十篇】快速介绍一致性Hash算法

前言&#xff1a; 在分布式系统中&#xff0c;数据的分布和负载均衡是至关重要的问题。一致性哈希算法是一种解决这些挑战的有效工具&#xff0c;它在分布式存储、负载均衡和缓存系统等领域得到了广泛应用。 随着互联网规模的不断扩大&#xff0c;传统的哈希算法在面对大规模…

cmake进阶:变量的作用域(目录作用域与全局作用域)

一. 简介 前面从函数作用域方面学习了变量的作用域&#xff0c;本文从目录作用域方面来学习变量的作用域。 二. cmake进阶&#xff1a;从目录作用域方面学习变量的作用域 1. 目录作用域 什么是目录作用域&#xff1f; 我把这个作用域叫做目录作用域。子目录会将父目录的所…

Web3 ETF软件系统的主要功能

下面是Web3 ETF系统软件的主要功能&#xff0c;这些功能共同构成了Web3 ETF系统软件的核心&#xff0c;使其能够有效地为投资者提供Web3技术相关的投资机会&#xff0c;同时确保合规性、安全性和透明度。北京木奇移动软件有限公司&#xff0c;专业的软件外包开发公司&#xff0…

【Git】Git学习-10-11:GitHub,SHH配置,克隆仓库

学习视频链接&#xff1a;【GeekHour】一小时Git教程_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 创建仓库 配置SSH密钥可以更加安全&#xff0c;方便地推送、拉取代码 根目录下&#xff0c;进入.ssh文件&am…

【C语言】——联合体与枚举

【C语言】——联合体与枚举 一、联合体1.1、联合体类型的声明1.2、联合体的特点1.3、相同成员的结构体和联合体对比1.4、联合体的大小计算1.5、联合体的应用举例 二、枚举2.1、枚举类型的声明2.2、枚举类型的优点 一、联合体 1.1、联合体类型的声明 联合体也叫做共用体   与…

学习R语言第五天

文章目录 语法学习创建数据的方式绘制图形的方式图形添加颜色如何操作数据的方式数据进行验算的判断加付值的方式修改变量名称的方式判断是否存在缺失值在计算的方式忽略缺失值通过函数的方式忽略缺失值日期处理的方式字符串转化成日期的方式格式化数据框中数据返回当前的日期的…

19_Scala集合概述

文章目录 集合回顾javaScala集合三大类String & StringBuilderScala集合两大类 集合 回顾java scala与Java有所不同 函数式编程语言更侧重集合本身提供的哪些功能&#xff1b; Scala集合三大类 1.Seq 存储有序数据可重复 类比 List 2.Set 存储无序数据不可重复 3.Map…

【算法系列】字符串

目录 leetcode题目 一、最长公共前缀 二、最长回文子串 三、二进制求和 四、字符串相加 五、字符串相乘 六、仅仅反转字母 七、字符串最后一个单词的长度 八、验证回文串 九、反转字符串 十、反转字符串 II 十一、反转字符串中的单词 III leetcode题目 一、最长公…

frp内网穿透服务搭建与使用

frp内网穿透服务搭建与使用 1、frp简介 frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议。 可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。frp工作原理 服务端运行&#xff0c;监听一个主端口…

Parts2Whole革新:多参照图定制人像,创新自定义肖像生成框架!

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; Parts2Whole革新&#xff1a;多参照图定制人像&#xff0c;创新自定义肖像生成框架&#xff01; 引言&#xff1a;探索多条件人像生成的新篇章 在数字内容创作…

论文精读-存内计算芯片研究进展及应用

文章目录 论文精读-存内计算芯片研究进展及应用概述背景介绍前人工作 存内计算3.1 SRAM存内计算3.2 DRAM存内计算3.3 ReRAM/PCM存内计算3.4 MRAM存内计算3.5 NOR Flash存内计算3.6 基于其他介质的存内计算3.7 存内计算芯片应用场景 总结QA 论文精读-存内计算芯片研究进展及应用…

SpringBoot中实现发送邮件

概要 在Spring Boot中发送电子邮件相对简单。你可以使用Spring的邮件支持来实现这一点。 步骤&#xff1a; 1.添加依赖&#xff1a;首先&#xff0c;需要在你的pom.xml文件中添加Spring Boot的邮件发送器依赖。 2. 配置邮件服务器&#xff1a;在application.properties或app…

嵌入式全栈开发学习笔记---C语言笔试复习大全14

目录 指针初级 指针的概念 指针类型 指针类型长度 指针的定义 通过指针访问数据 p1和*p1的区别 指针做函数参数 上一篇复习了8道编程题&#xff0c;这篇开始正式复习之指针&#xff01; 说明&#xff1a;我们学过单片机的一般都是有C语言基础的了&#xff0c;网上关于C…

网络 IO 模式

同步 IO 与异步 IO 同步 IO 和异步 IO 是关于数据读写方式的两种不同模式。 同步 IO 是指在程序读写数据时&#xff0c;需要等待操作完成后才能继续执行后面的程序。这种模式下&#xff0c;当程序使用阻塞式 IO 时&#xff0c;会一直等待IO操作完成&#xff0c;程序会暂停执行…

​​【收录 Hello 算法】3.3 数字编码

目录 3.3 数字编码 3.3.1 原码、反码和补码 3.3.2 浮点数编码 3.3 数字编码 Tip 在本书中&#xff0c;标题带有 * 符号的是选读章节。如果你时间有限或感到理解困难&#xff0c;可以先跳过&#xff0c;等学完必读章节后再单独攻克。 3.3.1 原码、反码和补码 在…

一、RocketMQ基本概述与部署

RocketMQ基本概述与安装 一、概述1.MQ概述1.1 用途1.2 常见MQ产品1.3 MQ常用的协议 2.RocketMQ概述2.1 发展历程 二、相关概念1.基本概念1.1 消息&#xff08;Message&#xff09;1.2 主题&#xff08;Topic&#xff09;1.3 标签&#xff08;Tag&#xff09;1.4 队列&#xff0…

RK3576芯片规格,以及与RK3588对比

瑞芯微RK3576是一款高性能、低功耗的SoC&#xff08;系统级芯片&#xff09;处理器&#xff0c;适用于基于ARM的PC、边缘计算设备、个人移动互联网设备等多种应用场景。它采用Arm架构的八核心CPU&#xff0c;集成了GPU、MCU、NPU、VPU等多种计算核心&#xff0c;并具有丰富的外…

Go Web 开发 Demo【用户登录、注册、验证】

前言 这篇文章主要是学习怎么用 Go 语言&#xff08;Gin&#xff09;开发Web程序&#xff0c;前端太弱了&#xff0c;得好好补补课&#xff0c;完了再来更新。 1、环境准备 新建项目&#xff0c;生成 go.mod 文件&#xff1a; 出现报错&#xff1a;go: modules disabled by G…

ttkbootstrap界面美化系列之Menubutton(五)

一&#xff1a;Menubutton接口 print(help(help(ttk.Menubutton))) Help on class Menubutton in module tkinter.ttk:class Menubutton(Widget)| Menubutton(masterNone, **kw)|| Ttk Menubutton widget displays a textual label and/or image, and| displays a menu wh…

Qt | QComboBox(组合框)

01、上节回顾 Qt 基础教程合集02、QComBox 一、QComboBox 类(下拉列表、组合框) 1、QComboBox 类是 QWidget 类的直接子类,该类实现了一个组合框 2、QComboBox 类中的属性 ①、count:const int 访问函数:int count() const; 获取组合框中的项目数量,默认情况下,对于空…