28. Python logging日志模块下(适合小白)

news2024/9/20 8:47:41

28. Python logging日志模块下(适合小白)

文章目录

  • 28. Python logging日志模块下(适合小白)
    • 1. %占位符格式化语法知识回顾
    • 2. basicConfig函数的参数
    • 3. format参数:设置输出的格式
      • 3.1 添加`%(asctime)s`字段输出日志发生时间
      • 3.2 `%(message)s`输出日志的文本信息
      • 3.3 format参数有多个值
      • 3.4 `%(levelname)s`输出日志的级别
    • 4. format参数字段名称
    • 5. logging 模块在爬虫实战中的应用
      • 5.1 源代码
      • 5.2 模块代码知识解析

1. %占位符格式化语法知识回顾

原文链接:45. Python 的%占位符格式化处理

【%占位符格式化语法】

(要输出的内容 % 要格式化的变量或数值)

【代码示例】

print("我的体重是%s公斤。"  %  50)

【终端输出】

我的体重是50公斤。

【语法解析】

  1. 要输出的内容为:我的体重是%s公斤

  2. %占位符。

  3. 要格式化的数值是:50

%s可以将整数、浮点数格式化为字符串类型。

【格式化语法书写步骤】

  1. 先写要输出的内容我的体重是50公斤。

  2. %s替换需要格式化的地方。

这里需要格式化的是数字50

那就用%s替代数字50

注意这里最终要输出的字符串类型,所以用%s占位。

如果需要输出的整数,则用%d去占位。

print("我的体重是%s公斤。")
  1. 添加%占位符。为了语法美观,我通常在%前后都输入一个空格。
print("我的体重是%s公斤。" % )
  1. 最后添加要格式化的数值。

这里要格式化的数值是50,因此在%号后面接50

print("我的体重是%s公斤。" % 50)

【终端输出】

我的体重是50公斤。

2. basicConfig函数的参数

basic[ˈbeɪsɪk]:基本的。

config[kənˈfɪg]:配置。

basicConfig:基本配置。

【basicConfig函数定义的参数】

basicConfig(*, 
            filename=..., 
            filemode=..., 
            format=..., 
            datefmt=..., 
            style=..., 
            level=..., 
            stream=..., 
            handlers=...)
  1. filename 参数:文件的路径。

  2. filemode 参数:创建文件的模式。

  3. format参数:设置输出的格式。

format[ˈfɔːmæt]:格式化。

  1. datefmt:指定输出日期及时间的格式。

  2. level:指定输出的日志级别。

level[ˈlevl]:等级。

3. format参数:设置输出的格式

format[ˈfɔːmæt]:格式化。

3.1 添加%(asctime)s字段输出日志发生时间

【体验代码】

import logging
logging.basicConfig(format="%(asctime)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

2023-04-24 22:00:24,322
2023-04-24 22:00:24,323
2023-04-24 22:00:24,324

运行上面的代码,终端输出了程序执行代码的时间,即日志发生的时间。

【温馨提示1】

运行上面的代码后,终端只输出了3行运行结果。

这是因为在不改变级别参数level的情况下,程序默认输出warning级别及以上级别的日志。

因此,这里只会输出warning , error, critical3个级别的日志发生的时间。

debug和info级别的日志发生的时间不会被输出。

【修改日志级别参数】

如果我只想输出ERROR级别以上的日志,那我可以通过修改日志级别参数level实现。

import logging
logging.basicConfig(level=logging.ERROR, format="%(asctime)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

2023-04-24 22:03:08,987
2023-04-24 22:03:08,988

运行上面的代码,程序终端只输出了2行运行结果。

level=logging.ERROR

这是因为当我们将basicConfig函数的level参数的值设置为ERROR时,程序终端只输出error及error级别以上日志发生的时间。

因此只会有2行输出。

【温馨提示2】

2023-04-24 22:03:08,987
2023-04-24 22:03:08,988

观察输出结果,我们发现程序只输出了时间,没有输出日志级别对应的文本信息。

所有信息!一般信息!警告信息!这些提示信息就是日志的文本信息。

原因如下:

【代码段1】

import logging
logging.basicConfig( )
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

WARNING:root:警告信息!
ERROR:root:严重信息!
CRITICAL:root:最严重信息!

当我们没有设置basicConfig函数的format参数时,程序默认输出文本信息。

【代码段2】

import logging
logging.basicConfig(format="%(asctime)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

2023-04-24 23:09:21,464
2023-04-24 23:09:21,466
2023-04-24 23:09:21,467

当我们修改basicConfig函数的format参数时,程序会根据参数的值输出对应的信息。

logging.basicConfig(format="%(asctime)s")

当将basicConfig函数的format参数值指定为%(asctime)s时,表示只输出日志发生的时间。

【总结】

format="%(asctime)s"的作用就是输出日志发生的时间。

【语法解析】

logging.basicConfig(format="%(asctime)s")
  1. format是参数名。

format[ˈfɔːmæt]:格式化。

  1. format参数后接等于号=

  2. 等于号后接英文引号" "

  3. %可以参考基础语法里学习的%占位符格式化语法。这里我把%理解成格式化占位符。

原文链接:45. Python 的%占位符格式化处理

  1. 英文圆括号()

  2. asctime。字段名称,该字段告诉程序要输出日志发生的时间。

字段名称放在英文圆括号里。

  1. s表示格式化为字符串。

【输出日志发生的时间代码示例】

format="%(asctime)s"

3.2 %(message)s输出日志的文本信息

上面的代码只输出了日志发生的时间,没有输出日志文本信息。

如果需要输出日志文本信息,那多加一个字段%(message)s即可。

【输出日志运行时间代码示例】

format="%(asctime)s"

【输出日志文本信息代码示例】

format="%(message)s"

【只输出文本信息代码】

import logging
logging.basicConfig(format="%(message)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

警告信息!
严重信息!
最严重信息!

运行上面的代码,程序只输出了日志文本信息。

【语法解析】

logging.basicConfig(format="%(message)s")
  1. format是参数名。

format[ˈfɔːmæt]:格式化。

  1. 参数后接等于号=

  2. 等于号=后接英文引号" "

  3. %格式化占位符。

  4. 英文圆括号( )

  5. message。字段名称,作用是输出日志文本信息。

message[ˈmesɪdʒ]:消息。

  1. s格式化为字符串。

3.3 format参数有多个值

format参数同时输出多个字段时,有多种语法结构。

1. 多个字段共用一对引号,字段之间用空格间隔

import logging
logging.basicConfig(format="%(asctime)s %(message)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

2023-04-24 23:15:00,035 警告信息!
2023-04-24 23:15:00,036 严重信息!
2023-04-24 23:15:00,036 最严重信息!

【代码示例】

logging.basicConfig(format="%(asctime)s %(message)s")

运行上面的代码我们可以同时输出日志发生的时间和日志文本信息。

多个字段共用1个引号,字段之间用一个空格间隔,输出的样式为:

2023-04-24 23:15:00,035 警告信息!
2023-04-24 23:15:00,036 严重信息!
2023-04-24 23:15:00,036 最严重信息!

即输出的时间和文本信息之间有空格。

2.多个字段共用一个引号,字段之间用英文逗号,间隔

import logging
logging.basicConfig(format="%(asctime)s,%(message)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

2023-04-24 23:17:46,449,警告信息!
2023-04-24 23:17:46,450,严重信息!
2023-04-24 23:17:46,451,最严重信息!

多个字段共用1个引号,字段之间用一个英文逗号,间隔,输出的样式为:

2023-04-24 23:17:46,449,警告信息!
2023-04-24 23:17:46,450,严重信息!
2023-04-24 23:17:46,451,最严重信息!

即输出的时间和文本信息之间有一个英文逗号,

3.每个字段各自用自己的引号

import logging
logging.basicConfig(format="%(asctime)s" "%(message)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

2023-04-24 23:19:29,278警告信息!
2023-04-24 23:19:29,280严重信息!
2023-04-24 23:19:29,282最严重信息!

每个字段用自己的引号,则输出日志发生时间和文本信息之间不会有任何间隔,而是紧密相连。

为了终端输出美观且便于观察,推荐用第1种语法结构。

【温馨提示】

当多个字段都用自己的引号时,字段之间就不能添加英文逗号等符号,否则程序会报错。

import logging
logging.basicConfig(format="%(asctime)s", "%(message)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

SyntaxError: positional argument follows keyword argument

positional argument follows keyword argument位置参数跟在关键字参数后面。

【语法结构总结】

# 用空格间隔输出内容(推荐)
logging.basicConfig(format="%(asctime)s %(message)s")
# 用英文逗号间隔输出内容
logging.basicConfig(format="%(asctime)s,%(message)s")
# 输出的内容紧密相连,没有间隔
logging.basicConfig(format="%(asctime)s" "%(message)s")

【语法提示】

format参数中可以添加多个字段,当有多个字段名称的时候,建议字段名称共用一个引号,字段名称之间用空格隔开。

3.4 %(levelname)s输出日志的级别

import logging
logging.basicConfig(format="%(asctime)s %(message)s %(levelname)s")
logging.debug('所有信息!') 
logging.info('一般信息!') 
logging.warning('警告信息!') 
logging.error('严重信息!') 
logging.critical('最严重信息!') 

【终端输出】

2023-04-25 12:36:50,801 警告信息! WARNING
2023-04-25 12:36:50,802 严重信息! ERROR
2023-04-25 12:36:50,803 最严重信息! CRITICAL

%(asctime)s字段输出日志发生时间2023-04-25 12:36:50,801

%(message)s输出日志的文本信息警告信息!

%(levelname)s输出日志级别WARNING

语法结构都是一样的:

  1. %格式化占位符。

  2. (levelname)s字段名称。

  3. s格式化为字符串。

4. format参数字段名称

可以用于format参数格式字符串的字段还有很多,如下图所示:

在这里插入图片描述

各字段语法结构都是一致的,这里就不在赘述。

推荐一篇比较全的logging知识文档,链接如下:

python之日志处理 (一)

5. logging 模块在爬虫实战中的应用

5.1 源代码

import json
from os import makedirs
from os.path import exists
import requests
import logging
import re
from urllib.parse import urljoin
import multiprocessing

logging.basicConfig(filename="26日志.log", level=logging.INFO,
                    format='%(asctime)s - %(levelname)s: %(message)s')

BASE_URL = 'https://ssr1.scrape.center'
TOTAL_PAGE = 10

RESULTS_DIR = 'json数据'
exists(RESULTS_DIR) or makedirs(RESULTS_DIR)


def scrape_page(url):
    """
    scrape page by url and return its html
    :param url: page url
    :return: html of page
    """
    logging.info('scraping %s...', url)
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        logging.error('get invalid status code %s while scraping %s',
                      response.status_code, url)
    except requests.RequestException:
        logging.error('error occurred while scraping %s', url, exc_info=True)


def scrape_index(page):
    """
    scrape index page and return its html
    :param page: page of index page
    :return: html of index page
    """
    index_url = f'{BASE_URL}/page/{page}'
    return scrape_page(index_url)


def parse_index(html):
    """
    parse index page and return detail url
    :param html: html of index page
    """
    pattern = re.compile('<a.*?href="(.*?)".*?class="name">')
    items = re.findall(pattern, html)
    if not items:
        return []
    for item in items:
        detail_url = urljoin(BASE_URL, item)
        logging.info('get detail url %s', detail_url)
        yield detail_url


def scrape_detail(url):
    """
    scrape detail page and return its html
    :param page: page of detail page
    :return: html of detail page
    """
    return scrape_page(url)


def parse_detail(html):
    """
    parse detail page
    :param html: html of detail page
    :return: data
    """

    cover_pattern = re.compile(
        'class="item.*?<img.*?src="(.*?)".*?class="cover">', re.S)
    name_pattern = re.compile('<h2.*?>(.*?)</h2>')
    categories_pattern = re.compile(
        '<button.*?category.*?<span>(.*?)</span>.*?</button>', re.S)
    published_at_pattern = re.compile('(\d{4}-\d{2}-\d{2})\s?上映')
    drama_pattern = re.compile('<div.*?drama.*?>.*?<p.*?>(.*?)</p>', re.S)
    score_pattern = re.compile('<p.*?score.*?>(.*?)</p>', re.S)

    cover = re.search(cover_pattern, html).group(
        1).strip() if re.search(cover_pattern, html) else None
    name = re.search(name_pattern, html).group(
        1).strip() if re.search(name_pattern, html) else None
    categories = re.findall(categories_pattern, html) if re.findall(
        categories_pattern, html) else []
    published_at = re.search(published_at_pattern, html).group(
        1) if re.search(published_at_pattern, html) else None
    drama = re.search(drama_pattern, html).group(
        1).strip() if re.search(drama_pattern, html) else None
    score = float(re.search(score_pattern, html).group(1).strip()
                  ) if re.search(score_pattern, html) else None

    return {
        'cover': cover,
        'name': name,
        'categories': categories,
        'published_at': published_at,
        'drama': drama,
        'score': score
    }


def save_data(data):
    """
    save to json file
    :param data:
    :return:
    """
    name = data.get('name')
    data_path = f'{RESULTS_DIR}/{name}.json'
    json.dump(data, open(data_path, 'w', encoding='utf-8'),
              ensure_ascii=False, indent=2)


def main(page):
    """
    main process
    :return:
    """
    index_html = scrape_index(page)
    detail_urls = parse_index(index_html)
    for detail_url in detail_urls:
        detail_html = scrape_detail(detail_url)
        data = parse_detail(detail_html)
        logging.info('get detail data %s', data)
        logging.info('saving data to json file')
        save_data(data)
        logging.info('data saved successfully')


if __name__ == '__main__':
    pool = multiprocessing.Pool()
    pages = range(1, TOTAL_PAGE + 1)
    pool.map(main, pages)
    pool.close()

    print("程序结束!")

参考链接:爬虫实战练习:提取电影详细信息(崔庆才2.5)

5.2 模块代码知识解析

1.导入模块

import logging

import[ˈɪmpɔːt]:引入,导入。

logging:模块名。

import logging导入logging日志模块。

2.调用basicConfig函数

import logging
logging.basicConfig(filename="26日志.log", level=logging.INFO,
                    format='%(asctime)s - %(levelname)s: %(message)s')

【代码示例】

import logging
logging.basicConfig( )

logging:模块名。

basicConfig( )函数名。

basic[ˈbeɪsɪk]:基本的。

config[kənˈfɪg]:配置。

basicConfig:基本配置。

3.basicConfig函数的参数

import logging
logging.basicConfig(filename="26日志.log", level=logging.INFO,
                    format='%(asctime)s - %(levelname)s: %(message)s')

【参数filename】

filename="26日志.log"

参数filename表示路径,意思是将日志输出到"26日志.log"文件中。

【参数level】

level=logging.INFO

参数level设置输出日志的级别。这里输出INFO级别及该级别以上级别的日志。

【参数format】

format='%(asctime)s - %(levelname)s: %(message)s'

format参数设置输出日志的格式。

%(asctime)s输出日志发生时间。

%(levelname)s输出日志级别。

%(message)s输出日志文本信息。

运行爬虫代码后,输出内容如下图所示:

在这里插入图片描述

上述图片的文本内容是怎么来的呢,我们得分析后面的代码。

这里的文本信息输出有2种,我们讲解第一种:

【代码示例】

def scrape_page(url):
    """
    scrape page by url and return its html
    :param url: page url
    :return: html of page
    """
    logging.info('scraping %s...', url)
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        logging.error('get invalid status code %s while scraping %s',
                      response.status_code, url)
    except requests.RequestException:
        logging.error('error occurred while craping %s', 
                    url, 
                    exc_info=True)
        logging.info('scraping %s...', url)

我们提取上面代码中涉及logging文本信息的代码,如下所示:

logging.info('scraping %s...', url)

上面的代码控制了日志输出的文本信息内容。

下面是爬虫代码运行正常时输出的部分日志:

2023-04-01 09:14:46,887 - INFO: scraping https://ssr1.scrape.center/page/1...
2023-04-01 09:14:46,909 - INFO: scraping https://ssr1.scrape.center/page/2...
2023-04-01 09:14:46,951 - INFO: scraping https://ssr1.scrape.center/page/3...
2023-04-01 09:14:46,954 - INFO: scraping https://ssr1.scrape.center/page/4...

输出的日志含有3部分信息:

输出日志发生的时间2023-04-01 09:14:46,887

输出日志的级别INFO

输出日志的文本信息https://ssr1.scrape.center/page/1...

能输出这3部分内容是basicConfig函数的format参数决定的,如下所示:

format='%(asctime)s - %(levelname)s: %(message)s'

- INFO:前面的小横线和后面的英文冒号就是上面代码字段名称之间的添加的符号。

format参数有3个,决定了日志可以输出3部分内容,即时间、级别及文本信息。

而具体输出什么样的文本信息是由下面的代码决定的:

logging.info('scraping %s...', url)

为了方便大家理解,我把上面的代码修改成中文样式:

logging.info('访问的网址是 %s ', url)

实例代码中的info语句文本信息是不固定的,因为url是一个动态的变量。

logging.info('一般信息!') 

我么之前使用的info语句文本信息是固定的,只是一行字符串。

假设我们要访问某网页的前5页网址,如下所示:

https://ssr1.scrape.center/page/1
https://ssr1.scrape.center/page/2
https://ssr1.scrape.center/page/3
https://ssr1.scrape.center/page/4
https://ssr1.scrape.center/page/5

我们用logging的方式输出上面的网址:

【步骤分解】

  1. 生成动态的网址

range(1,6)含前不含后,输出的数字是1到5,不含6。

for i in range(1,6):
    url = ("https://ssr1.scrape.center/page/%d" % i)
    print(url)

【终端输出】

https://ssr1.scrape.center/page/1
https://ssr1.scrape.center/page/2
https://ssr1.scrape.center/page/3
https://ssr1.scrape.center/page/4
https://ssr1.scrape.center/page/5

用for循环和%格式化占位符方法输出控制网址页码的部分:

import logging
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(levelname)s: %(message)s')
for i in range(1,6):
    url = ("https://ssr1.scrape.center/page/%d" % i)
    logging.info('访问的网址是 %s ', url)

【终端输出】

2023-04-25 22:55:38,736 - INFO: 访问的网址是 https://ssr1.scrape.center/page/1 
2023-04-25 22:55:38,737 - INFO: 访问的网址是 https://ssr1.scrape.center/page/2 
2023-04-25 22:55:38,738 - INFO: 访问的网址是 https://ssr1.scrape.center/page/3 
2023-04-25 22:55:38,738 - INFO: 访问的网址是 https://ssr1.scrape.center/page/4 
2023-04-25 22:55:38,739 - INFO: 访问的网址是 https://ssr1.scrape.center/page/5 

这里的%d和%s都是字符串格式化的语法,不理解的需要回顾之前的内容。

运行上面的代码日志输出到了终端。

如果需要将日志输出到log文件中,需要添加一个filename字段。

import logging
logging.basicConfig(level=logging.INFO,
                    filename="28日志.log",
                    format='%(asctime)s - %(levelname)s: %(message)s')
for i in range(1,6):
    url = ("https://ssr1.scrape.center/page/%d" % i)
    logging.info('访问的网址是 %s ', url)

大家可以在28.log文件中查看输出内容。

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

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

相关文章

电子商务网站上的API攻击如何泄漏PII

本稳重点分享&#xff1a; 以影子 API为目标的 API 攻击 电子商务网站上的 API 攻击如何泄漏 PII 对 API 运行时安全性重要性的看法 API 渗透测试指南 以影子 API为目标的 API 攻击 首先是DarkReading最近的一个研究的报告&#xff0c;该报告显示&#xff0c;大约50亿&am…

20+ Prompt工具网站汇总;我用AI工具开了一家「无人公司」;如何10分钟上线一个AI导航网站;第一部AIGC中英双语图文辞典 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 『MidJourney Prompt工具网站』加速生成与优化&#xff0c;持续更新中 ShowMeAI知识星球 | 资源标签&#xff1a;找工具 这是一个总结…

【unity专题篇】——GUI(IMGUI)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

tcp,udp一些列问题

&#xff08;tcp,udp基本介绍&#xff0c;三握四挥等&#xff09;七层模型主要知识点等 OSI七层模型其功能简介 分层机制体现了分治的思想&#xff0c;每一层为上一层提供保障屏蔽异构。 物理层&#xff1a;规定了一系列的物理、电气、接口标准&#xff0c;传输的是比特流&…

DAY05_面向对象基础

面向对象并不是一个技术&#xff0c;而是一种指导思想。 为什么要用面向对象编程&#xff1f; 因为生活中&#xff0c;我们解决问题时&#xff0c;就是采用这种指导思想去解决的。所以&#xff0c;我们写程序去解决问题时&#xff0c;如果也能采用这种指导思想就会使得程序变…

LVS+keepalived 群集

Keepalived及其工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题 在一个LVS服务集群中通常有主服务器&#xff08;MASTER&#xff09;和备份服务器&#xff08;BACKUP&#xff09;两种角色的服务器&#xff…

链接伪类选择器(上)

知识点&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http-equiv"X-UA-Compatible" content"IEedge"> <meta name"viewport" c…

java方法的重载

java中有很多方法是可以通过重载的方式实现的&#xff0c;这是 Java语言的一大特色&#xff0c;但是同时也为开发人员带来了一些麻烦&#xff0c;不知道怎么去调用这些方法&#xff0c;而且还容易出现一种情况就是&#xff1a;明明已经调用过了一个方法&#xff0c;但为什么又要…

Ansys Zemax | 如何模拟双折射偏振器件

这篇文章介绍了什么是双折射现象、如何在OpticStudio中模拟双折射 (birefringence)、如何模拟双晶体的双折射偏振器以及如何计算偏振器的消光比。&#xff08;联系我们获取文章附件&#xff09; 什么是双折射现象 一般的光学材料都是均匀的各向同性的&#xff0c;也就是说无论光…

等级保护、风险评估和安全测评分别是什么?

2022-06-17 15:17 迈入“等保2.0时代”以后&#xff0c;我国对于等级保护的要求更为严格和具体。等级保护、风险评估和安全测评这三个词&#xff0c;也因此总是出现在人们的视野之中&#xff0c;还总是被混淆。那这三者究竟分别是什么呢&#xff1f;如何区分它们&#xff1f;它…

如何以产品经理思维打造一所高品质学校?

学校的建设与管理真不是一件容易事。2023年03月17日&#xff0c;山东菏泽市曹县一家长投诉某中学课业繁重&#xff0c;孩子经常写作业到半夜&#xff1b;2023年4月4日&#xff0c;张先生在华龙网重庆网络问政平台投诉万州区某中学伙食差&#xff0c;指出“发灰的洋葱&#xff0…

本地运行 minigpt-4

1.环境部署 参考官方自带的README.MD&#xff0c;如果不想看官方的&#xff0c;也可参考MiniGPT-4&#xff5c;开源免费可本地进行图像对话交互的国产高级大语言增强视觉语言理解模型安装部署教程 - openAI 当然&#xff0c;所有的都要按照作者说明来&#xff0c;特别是版本号…

练好基本功,优秀工程师成长第一步

计算机基础作用 举例1&#xff1a;若是我们要开发大规模应用系统&#xff0c;如电商服务系统&#xff0c;要考虑很多 1. 这个服务应用要用什么语言来编写&#xff1f; 2. 是采用单体进程&#xff0c;还是用多个进程来协同工作&#xff1f; 3. 如何管理长期使用的内存空间&a…

( 栈和队列) 155. 最小栈 ——【Leetcode每日一题】

❓155. 最小栈 难度&#xff1a;中等 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。…

WiFi电子标签简介

WiFi电子标签系统概述&#xff1a; WIFI电子办公标牌系统是一种先进的无线自动更新系统&#xff0c;取代了传统的纸质标牌/桌牌需要人工更换的方式。WIFI ESL系统只需要一个电子办公标志设备&#xff0c;让它在办公或会议空间工作&#xff0c;快速改变人员或会议信息。这是一种…

Docker -compose 安装使用

命令 总结 yum install docker-compose-plugin docker compose version docker compose up docker compose up -d相关的配置。 创建docker-conpose 目录&#xff0c;并创建docker-compose.yml文件 version: 3 services: mysql: image: mysql restart: always co…

【基础算法】二叉树相关题目

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招算法的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于代码随想录进行的&#xff0c;每个算法代码参考leetcode高赞回答和…

[ICLR 2023] Token Merging: Your ViT But Faster

Contents IntroductionToken MergingExperimentsImage ExperimentsDesign choicesModel SweepComparison to Other WorksVisualizations Video ExperimentsAudio Experiments References Introduction 作者提出了一种 token 合并方法 Token Merging (ToMe)&#xff0c;能够在不…

【Tasking_IDE】-1-如何让目录下的C文件不参与编译

案例背景&#xff1a; 当您在使用Tasking TriCore Eclipse IDE集成开发环境编译时&#xff0c;是不是有时遇到这样一个问题&#xff1a;导入了一个算法/驱动文件夹&#xff0c;但文件夹里面不是所有的C文件都要参与编译&#xff0c;于是您可能想到把这些“不参与编译的文件”删…

Kafka3.0.0版本——生产者 数据去重

目录 一、数据传递语义1.1、至少一次1.2、最多一次1.3、精确一次 二、幂等性2.1、幂等性原理2.2、重复数据的判断标准2.3、如何使用幂等性 三、生产者 事务3.1、Kafka事务原理3.2、Kafka事务注意事项3.3、Kafka事务的5个API3.3.1、初始化事务API3.3.2、开启事务API3.3.3、在事务…