0%

简介

  • Redis相关笔记

redis是什么

Redis是一个开源的内存数据库,它可以用作键值存储、缓存和消息队列。Redis支持各种数据结构,如字符串、哈希、列表、集合、有序集合等,这使得它非常灵活和多用途。它通常被用来加速应用程序的性能,存储会频繁访问的数据,或者作为分布式系统中的数据存储和消息传递中间件。Redis的速度非常快,因为它将数据存储在内存中,并且可以通过持久化机制将数据保存到磁盘上以进行持久化存储。

Redis(维基百科)

  • Redis(Remote Dictionary Server)是一个使用ANSI C编写的支持网络,基于内存,分布式,可选持久性的键值对存储数据库。

  • 数据模型

    • Redis的外围由一个键,值映射的字典构成。与其他非关系型数据库主要不同在于: Redis中值的类型不仅限于字符串,还支持如下抽象数据类型
      • 字符串列表
      • 无序不重复的字符串集合
      • 有序不重复的字符串集合
      • 键,值都为字符串的哈希表
    • 值的类型决定了值本身支持的操作。Redis支持不同无序,有序的列表,无序,有序的集合间的交集,并集等高级服务器端原子操作
  • 持久化

    • Redis通常将全部数据存储在内存中
    • 目前通过两种方式实现持久化
      • 使用快照,一种半持久耐用模式。不时的将数据集以异步方式从内存以RDB格式写入硬盘
      • 1.1版本开始使用更安全的AOF格式替代,一种只能追加的日志类型。将数据集修改操作记录起来。Redis能够在后台对只可追加的记录进行修改,从而避免日志的无限增长。
  • 同步

    • Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。从盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助
  • 性能

    • 当数据依赖不再需要,Redis这种基于内存的性质,与在执行一个事务时将每个变化都写入硬盘的数据库系统相比就显得执行效率非常高。[11]写与读操作速度没有明显差别。

数据库 redis 详解

Redis是一个非常流行的开源内存数据库,它提供了丰富的功能和灵活的用途。下面是对Redis的一些详细解释:

  1. 内存数据库:Redis主要将数据存储在内存中,这使得它能够提供非常快速的读写操作。由于内存的速度远高于磁盘,因此Redis能够在毫秒级别处理大量的读写请求。

  2. 键值存储:Redis是一个键值存储系统,其中的每个键都与一个值相关联。这种简单的数据结构使得Redis在处理简单数据模型时非常高效。

  3. 数据结构支持:Redis支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等。这些数据结构使得Redis可以应对各种不同的需求,并提供了丰富的数据操作命令。

  4. 持久化存储:尽管Redis主要将数据存储在内存中,但它也提供了持久化存储功能,可以将数据定期保存到磁盘上,以防止数据丢失。

  5. 缓存:由于其快速的读写速度和灵活的数据结构,Redis经常被用作缓存系统。它可以将经常访问的数据存储在内存中,从而加速应用程序的性能。

  6. 发布/订阅:Redis支持发布/订阅模式,可以用作消息队列系统。发布者可以将消息发布到特定的频道,而订阅者则可以订阅这些频道以接收消息。

  7. 分布式系统支持:Redis提供了多种分布式特性,如主从复制、分片等,使得它可以在分布式系统中使用,并提供高可用性和可扩展性。

  8. 事务支持:Redis支持事务操作,可以将多个命令打包成一个原子操作,从而保证这些命令要么全部执行成功,要么全部执行失败。

总的来说,Redis是一个功能强大、性能优越的内存数据库,可以应对各种不同的应用场景,从简单的缓存系统到复杂的分布式系统都能够发挥作用。

linux redis C++相关工具库

在Linux环境下,有几个与Redis相关的C++工具库可以用来与Redis进行交互和操作。以下是其中一些:

  1. hiredis:hiredis是一个轻量级的C库,用于与Redis进行交互。虽然它是用C编写的,但也提供了C++的包装器,可以在C++项目中使用。hiredis提供了简洁的API,使得与Redis进行连接、发送命令和接收响应变得非常方便。

  2. cpp_redis:cpp_redis是一个用C++编写的Redis客户端库,提供了现代C++风格的API和异步支持。它的设计使得在C++应用程序中与Redis进行交互变得更加简单和高效。

  3. Redox:Redox是另一个用C++编写的Redis客户端库,它提供了类似于cpp_redis的现代C++接口,并支持异步操作。Redox的设计目标是提供简单易用的API,同时保持高性能。

这些工具库都可以在Linux环境下使用,并且都支持与Redis进行连接、命令发送、响应接收等操作。选择哪个库取决于你的项目需求和个人偏好,但无论选择哪个,它们都提供了方便、高效的方式来利用Redis的功能。

linux redis开发结构是什么样的

在Linux环境下进行Redis开发时,通常会采用一种分层结构来组织代码和实现功能。这种结构可以根据项目的规模和复杂度进行调整,但通常包含以下几个层次:

  1. 应用层:应用层是最高级别的层次,它包含与业务逻辑直接相关的代码。在这一层,开发者会编写与具体业务需求相关的功能,如数据处理、业务逻辑实现等。应用层通过调用下一层的接口来与Redis进行交互,发送命令、接收响应,并处理返回的数据。

  2. Redis客户端库:在应用层之下是Redis客户端库,它提供了与Redis服务器进行通信的API和功能。开发者可以使用已有的Redis客户端库,如hiredis、cpp_redis或Redox,也可以根据需要自行开发客户端库。这一层负责建立与Redis服务器的连接,发送命令和接收响应,并提供方便的接口供应用层调用。

  3. 网络通信层:在客户端库之下是网络通信层,它负责处理与Redis服务器之间的网络通信。这一层实现了与Redis服务器的连接建立、命令发送、响应接收等功能,通常使用TCP/IP协议来进行通信。

  4. Redis服务器:最底层是Redis服务器,它负责存储数据、处理命令、生成响应等功能。Redis服务器通常在Linux环境下运行,可以作为单机或分布式系统来部署和管理。

在这种结构下,应用层通过调用Redis客户端库提供的API与Redis进行交互,而客户端库则通过网络通信层与Redis服务器建立连接,并发送命令和接收响应。这种分层结构使得Redis开发更加模块化和可维护,同时也提供了灵活性和扩展性,能够适应不同规模和复杂度的项目需求。

redis的用途 详解

Redis 是一个开源的、基于内存的数据存储系统,它支持多种数据结构(如字符串、哈希表、列表、集合、有序集合等),并提供了丰富的功能和特性。Redis 的用途非常广泛,包括但不限于以下几个方面:

1. 缓存:

Redis 可以作为高性能的缓存系统,用于存储常用的数据,加速访问速度。由于 Redis 的数据存储在内存中,读写速度非常快,适合存储热点数据和频繁访问的数据。常见的缓存应用包括网页缓存、会话缓存、对象缓存等。

2. 数据库:

虽然 Redis 是一个键值存储系统,但它的数据结构支持丰富,可以存储复杂的数据类型,并提供了持久化功能,可以将数据持久化到磁盘上。因此,Redis 也可以作为轻量级的数据库使用,适用于一些对数据持久性要求不是很高的场景,如消息队列、计数器、排行榜等。

3. 分布式锁:

Redis 的原子操作和分布式特性使其成为实现分布式锁的一个理想选择。通过 Redis 的 SETNX(SET if Not eXists)命令可以很方便地实现分布式锁,保证在分布式环境下的数据一致性和并发安全性。

4. 消息队列:

Redis 的发布订阅功能使其成为一个简单而有效的消息队列系统。生产者可以将消息发布到指定的频道,而订阅者则可以订阅这些频道,并在有消息到达时接收并处理。这种发布-订阅模式非常适用于异步任务处理、消息广播等场景。

5. 实时排行榜和计数器:

由于 Redis 支持有序集合和原子操作,可以非常方便地实现实时排行榜和计数器功能。通过有序集合存储分数和成员的对应关系,可以实现按分数排序的排行榜,而通过增减操作可以实现实时计数器功能。

6. 地理位置应用:

Redis 的地理位置数据结构和地理位置计算命令,使其成为实现地理位置应用(如附近的人、地点推荐等)的一个良好选择。通过地理位置数据结构存储经纬度信息,并使用地理位置计算命令进行距离计算和位置查询,可以实现许多有趣的地理位置应用。

总结:

Redis 是一个功能强大、用途广泛的数据存储系统,可以应用于缓存、数据库、分布式锁、消息队列、实时计数器、地理位置应用等众多场景。其快速、高效、稳定的特性使其成为众多互联网应用的首选,是一个非常受欢迎的开源项目。

redis报文 详解

在 Redis 中,通信是通过简单的文本协议进行的,称为 Redis 协议(Redis Protocol)。Redis 协议是一种基于文本的、简单易懂的协议,它使用 RESP(REdis Serialization Protocol)格式来进行数据的序列化和反序列化。下面是关于 Redis 协议报文的详细解释:

1. RESP 格式:

RESP 是 Redis 自定义的一种序列化协议,用于在客户端和服务器之间传输数据。RESP 格式有以下几种类型:

  • 单行字符串(Simple Strings):以 “+” 开头,例如:+OK\r\n
  • 错误消息(Errors):以 “-“ 开头,例如:-Error message\r\n
  • 整数值(Integers):以 “:” 开头,例如::1000\r\n
  • 批量字符串(Bulk Strings):以 “$” 开头,例如:$6\r\nfoobar\r\n
  • 数组(Arrays):以 “*” 开头,例如:*3\r\n:1\r\n:2\r\n:3\r\n

2. Redis 协议报文示例:

下面是一个 Redis 协议报文的示例:

1
2
3
4
*3\r\n
$3\r\nSET\r\n
$5\r\nmykey\r\n
$7\r\nmyvalue\r\n

这个报文表示一个数组,包含三个元素,分别是一个字符串 SET、一个字符串 mykey 和一个字符串 myvalue。这个报文表示的操作是向 Redis 数据库中设置一个键值对,键为 mykey,值为 myvalue。

3. 报文的解析与处理:

在 Redis 客户端和服务器之间的通信过程中,客户端会向服务器发送一系列的命令请求报文,服务器接收到请求后进行解析和处理,然后返回相应的响应报文给客户端。客户端收到响应后进行解析并根据需要进行后续的操作。

4. 客户端和服务器之间的通信:

在实际的使用中,Redis 客户端和服务器之间的通信是通过套接字(Socket)来实现的。客户端通过套接字向服务器发送请求报文,服务器接收到请求后进行处理,并根据请求发送响应报文给客户端。

5. 序列化与反序列化:

Redis 协议中的报文需要进行序列化和反序列化操作,以便在网络上传输和在客户端/服务器中进行处理。客户端和服务器需要实现相应的序列化和反序列化算法来处理 Redis 协议报文。

总的来说,Redis 协议是一种简单易懂的文本协议,用于客户端和服务器之间的通信。通过使用 RESP 格式的报文,客户端可以向服务器发送命令请求,服务器接收到请求后进行处理,并返回相应的响应给客户端。这种基于文本的通信协议使得 Redis 在网络传输和数据处理方面具有良好的可扩展性和易用性。

redis有哪些数据结构

Redis 是一个支持多种数据结构的内存数据库,每种数据结构都有其特定的用途和优势。以下是 Redis 中常见的数据结构:

  1. 字符串(String):

    • 最基本的数据结构,存储一个键值对,键是字符串,值可以是字符串、整数或浮点数。
  2. 哈希表(Hash):

    • 类似于关联数组,存储字段和与其关联的值的映射关系,用于存储对象。
  3. 列表(List):

    • 双向链表结构,支持插入、删除、查找等操作,可以用作队列、栈等数据结构。
  4. 集合(Set):

    • 无序集合,元素唯一,支持添加、删除、查找等操作,可以用于存储唯一值。
  5. 有序集合(Sorted Set):

    • 类似于集合,每个元素都关联了一个分数(score),元素按照分数从小到大排序,支持添加、删除、查找等操作。
  6. 位图(Bitmap):

    • 由二进制位组成的数据结构,支持位运算操作,可以用于表示用户在线状态、标记用户行为等。
  7. HyperLogLog:

    • 用于基数估计的数据结构,用于估算集合中元素的数量。
  8. 地理空间索引(GeoSpatial):

    • 存储地理位置信息的数据结构,支持添加、删除、查找等操作,可以用于位置信息检索和计算。

这些数据结构使 Redis 能够满足不同场景下的需求,例如缓存、计数器、消息队列、排行榜等。在使用 Redis 时,根据具体需求选择合适的数据结构能够更好地发挥其性能和功能优势。

连接操作命令

  • quit : 关闭连接
  • auth : 简单密码认证
  • help cmd : 查看cmd帮助,例如:help quit

持久化

  • save : 将数据同步保存到磁盘
  • bgsave : 将数据异步保存到磁盘
  • lastsave : 返回上次成功将数据保存到磁盘的Unix时戳
  • shundown : 将数据同步保存到磁盘,然后关闭服务

远程服务控制

  • info : 提供服务器的信息和统计
  • monitor : 实时转储收到的请求
  • slaveof : 改变复制策略设置
  • config : 在运行时配置Redis服务器

对value操作的命令

  • exists (key) : 确认一个key是否存在
  • del (key) : 删除一个key
  • type (key) : 返回值的类型
  • keys (pattern) : 返回满足给定pattern的所有key
  • randomkey : 随即返回key空间的一个
  • keyrename(oldname, newname) : 重命名key
  • dbsize : 返回当前数据库中key的数目
  • expire : 设定一个key的活动时间(s)
  • ttl : 获得一个key的活动时间
  • select (index) : 按索引查询
  • move (key, dbindex) : 移动当前数据库中的key到dbindex数据库
  • flushdb : 删除当前选择数据库中所有key
  • flushall : 删除所有数据库中的所有key

List

  • rpush(key, value) : 在名称为key的list尾部添加一个值为value的元素
  • lpush(key, value) : 在名称为key的list头部添加一个值为alue的元素
  • llen(key) : 返回名称为key的list长度
  • lrange(key, start, end) : 返回名称为key的list中start至end之间的元素
  • ltrim(key, start, end) : 截取名称为key的list
  • lindex(key, index) : 返回名称为key的list中index位置的元素
  • lset(key, index, value) : 给名称为key的list中index位置的元素赋值
  • lrem(key, count, value) : 删除count个key的list中值为value的元素
  • lpop(key) : 返回并删除名称为key的list中的首元素
  • rpop(key) : 返回并删除名称为key的list中的尾元素
  • blpop(key1, key2, ... key N, timeout) : lpop命令的block版本
  • brpop(key1, key2, ... key N, timeout) : rpop的block版本

简介

  • Python编程语言的理论基础

python3 基础数据类型

Python 3 提供了多种 基础数据类型,这些数据类型可以用于存储各种形式的数据。以下是 Python 3 中常见的基础数据类型及其详细介绍:


1. 数值类型(Numeric Types)

1.1 整数 (int)

表示没有小数点的数字,可以是正数、负数或者零。

1
2
3
x = 10
y = -3
z = 0

1.2 浮点数 (float)

表示带有小数点的数字,通常用于科学计算。

1
2
3
a = 3.14
b = -0.001
c = 2.0

1.3 复数 (complex)

表示复数,格式为 a + bj,其中 a 是实数部分,b 是虚数部分,j 是虚数单位。

1
2
c1 = 3 + 4j
c2 = 1 - 2j

2. 布尔类型 (bool)

布尔类型只有两个值:TrueFalse,通常用于条件判断和逻辑运算。

1
2
x = True
y = False
  • TrueFalse 也可以通过数字表示:True 等于 1False 等于 0
1
2
x = int(True)  # 1
y = int(False) # 0

3. 字符串类型 (str)

字符串是由字符组成的序列,可以用单引号 (') 或双引号 (") 括起来,支持多行字符串的表示。

1
2
3
4
s1 = "Hello, world!"
s2 = 'Python'
s3 = '''This is a
multi-line string.'''

字符串是 不可变的,一旦创建后无法修改。


4. 列表类型 (list)

列表是 有序的可变的允许重复的元素集合。列表的元素可以是任意类型,包括其他列表。

1
2
3
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "apple", 3.14, [1, 2]]
  • 列表是可变的,可以通过索引访问、修改或添加元素。
1
2
fruits[1] = "orange"  # 修改
fruits.append("pear") # 添加

5. 元组类型 (tuple)

元组是 有序的不可变的允许重复的元素集合。元组一旦创建,无法修改其内容。

1
2
coordinates = (1, 2, 3)
colors = ("red", "green", "blue")
  • 元组使用小括号 () 创建,支持索引和切片,但不能修改其元素。
1
print(coordinates[0])  # 输出: 1

6. 集合类型 (set)

集合是 无序的不重复的元素集合。集合自动去重,常用于数学运算,如交集、并集、差集等。

1
2
fruits = {"apple", "banana", "cherry"}
numbers = {1, 2, 3, 4, 5}
  • 集合是无序的,不能通过索引访问。
  • 集合支持集合运算,如交集(&)、并集(|)、差集(-)。
1
2
3
4
5
a = {1, 2, 3}
b = {3, 4, 5}
print(a & b) # 输出: {3} 交集
print(a | b) # 输出: {1, 2, 3, 4, 5} 并集
print(a - b) # 输出: {1, 2} 差集

7. 字典类型 (dict)

字典是 无序的键值对(key-value)的集合。每个元素由一个键和一个值组成,可以通过键来快速查找对应的值。

1
person = {"name": "Alice", "age": 30, "city": "New York"}
  • 字典的键必须是不可变的类型(如字符串、整数、元组),而值可以是任意类型。
  • 字典是可变的,可以添加、修改和删除键值对。
1
2
3
person["age"] = 31  # 修改
person["job"] = "Engineer" # 添加
del person["city"] # 删除

8. None 类型 (NoneType)

None 是 Python 的特殊常量,表示空值或不存在的值。它常用于函数没有返回值时,或者需要表示一个空的对象。

1
x = None
  • None 是一个对象,可以用于表示“无”或“空”。
  • 它通常用于初始化变量或作为默认参数。

9. 可变与不可变类型

9.1 不可变类型

  • intfloatcomplexstrtuplefrozenset 都是不可变的类型。一旦创建,它们的值就不能改变。

9.2 可变类型

  • listsetdict 是可变的类型,可以修改其内容。

10. 类型转换

Python 提供了几种函数,用于在不同类型之间进行转换。

10.1 **int()**:将其他类型转换为整数。

1
2
x = int("123")  # 字符串转整数
y = int(3.14) # 浮点数转整数

10.2 **float()**:将其他类型转换为浮点数。

1
2
x = float("3.14")  # 字符串转浮点数
y = float(10) # 整数转浮点数

10.3 **str()**:将其他类型转换为字符串。

1
2
x = str(123)      # 整数转字符串
y = str(3.14) # 浮点数转字符串

10.4 **list()**:将其他可迭代对象转换为列表。

1
x = list("hello")  # 转为列表: ['h', 'e', 'l', 'l', 'o']

10.5 **tuple()**:将其他可迭代对象转换为元组。

1
x = tuple([1, 2, 3])  # 转为元组: (1, 2, 3)

10.6 **set()**:将其他可迭代对象转换为集合。

1
x = set([1, 2, 3, 3])  # 转为集合: {1, 2, 3}

11. 总结

数据类型 描述 示例
int 整数 10, -5, 0
float 浮点数 3.14, -0.001
complex 复数 3 + 4j
bool 布尔值 True, False
str 字符串 "Hello", 'Python'
list 列表(有序、可变) [1, 2, 3]
tuple 元组(有序、不可变) (1, 2, 3)
set 集合(无序、不重复) {1, 2, 3}
dict 字典(无序、键值对) {"name": "Alice", "age": 30}
None 空值 None

总结: Python 提供了多种基础数据类型,适用于不同场景。数值类型(int, float)适用于数学计算,布尔类型适用于逻辑判断,字符串用于处理文本数据,集合用于处理不重复的元素,而字典用于存储键值对映射。在 Python 中,理解这些基础数据类型及其特点是编写高效程序的基础。

python3 pip -U参数是什么意思

pip 命令中,-U 参数用于升级已经安装的包到最新版本。具体来说,-U 参数表示 “upgrade”,它告诉 pip 将指定的包升级到最新可用版本。

例如:

1
pip install -U package_name

这将会升级 package_name 到最新版本。如果 package_name 没有被安装,它将被安装;如果已经安装,将会被升级到最新版本。

使用 -U 参数是为了确保你使用的是包的最新版本,而不是旧版本。这在确保你使用的软件包具有最新特性、修复了已知问题或者提供了性能改进等方面是很有用的。

python3 str object is not callable

如果你在Python中遇到 “str object is not callable” 错误,通常是因为你意外地使用了内置函数的名称作为变量名。在Python中,避免使用内置函数名作为变量名是一个良好的实践。

例如,以下是一个可能导致该错误的示例:

1
2
3
str = "Hello"
result = str(42) # 这里会引发 "str object is not callable" 错误
print(result)

在这个例子中,str被重新赋值为一个字符串,然后试图调用它就会引发错误。为了避免这种情况,应该使用不同的变量名:

1
2
3
my_str = "Hello"
result = str(42) # 这里不会引发错误,因为 str 是内置函数
print(result)

确保不要覆盖内置函数和关键字的名称,以避免这种类型的错误。如果已经发生了这种情况,重新启动Python解释器并尽量避免使用与内置函数和关键字相同的变量名。

python3 no module named requests

如果您在 Python 3 中遇到 “no module named requests” 错误,这意味着您的 Python 环境中缺少 requests 模块。requests 是一个用于发送 HTTP 请求的常用库,但它不是 Python 的标准库,因此您需要单独安装它。

要解决这个问题,您可以执行以下步骤来安装 requests 模块:

  1. 使用 pip 安装 requests

    打开终端(命令行界面)并运行以下命令来使用 pip 安装 requests 模块:

    1
    pip install requests

    请确保 pip 是与您的 Python 3 版本相关联的 pip,通常情况下,您可以使用 pip3 命令来确保安装到 Python 3:

    1
    pip3 install requests
  2. 验证安装

    安装完成后,您可以在 Python 中导入 requests 模块并验证是否成功。打开 Python 解释器或脚本,尝试运行以下代码:

    1
    2
    import requests
    print(requests.__version__)

    如果没有出现错误,并且成功打印出 requests 版本号,那么说明安装已经成功。

请注意,如果您在虚拟环境中工作,请确保您的虚拟环境处于活动状态,以便 requests 模块安装到虚拟环境而不是全局 Python 环境。如果您使用的是 Python 3,pip 通常会默认安装到 Python 3 的环境中。

如果仍然遇到问题,可以提供更多详细信息,以便我更好地帮助您解决问题。

python3 pip 常用命令 详解

pip 是 Python 的包管理工具,用于安装、卸载和管理 Python 包(也称为库或模块)。以下是一些常用的 pip 命令及其详细解释:

  1. 安装包

    1
    pip install package_name

    用于安装指定的 Python 包。package_name 是要安装的包的名称。可以使用这个命令来安装第三方库,例如 numpyrequestsmatplotlib 等。可以使用 -r 选项从一个文本文件中安装一组包。

  2. 卸载包

    1
    pip uninstall package_name

    用于卸载指定的 Python 包。package_name 是要卸载的包的名称。

  3. 查看已安装的包

    1
    pip list

    显示已经安装的所有 Python 包的列表。

  4. 查看包的详细信息

    1
    pip show package_name

    显示指定包的详细信息,包括版本号、作者、描述等。

  5. 升级包

    1
    pip install --upgrade package_name

    用于升级已安装的包到最新版本。

  6. 搜索包

    1
    pip search search_term

    用于搜索 PyPI(Python Package Index)上的包。search_term 是您要搜索的包的关键字。

  7. 创建 requirements 文件

    1
    pip freeze > requirements.txt

    将当前环境中已安装的所有包及其版本号保存到 requirements.txt 文件中,通常用于共享项目的依赖信息。

  8. 从 requirements 文件安装包

    1
    pip install -r requirements.txt

    requirements.txt 文件中安装指定版本的包,用于在新环境中还原项目的依赖关系。

  9. 查看包的依赖关系

    1
    pip show --files package_name

    显示指定包的依赖关系和文件路径。

  10. 安装包的特定版本

    1
    pip install package_name==version

    安装指定版本的包,其中 version 是要安装的版本号。

这些是一些常用的 pip 命令,用于管理 Python 包。根据您的需求,您可以使用这些命令来安装、升级、卸载、查看和管理 Python 包。使用 pip 可以方便地管理Python项目的依赖关系。

kwargs

在 Python 中,kwargs 是一个特殊的参数,用于接收传递给函数的关键字参数(Keyword Arguments)。kwargs 是一个字典(dictionary),其中包含了函数调用时传递的关键字参数及其对应的值。

使用 **kwargs 语法可以在函数定义中接收关键字参数,并将其作为字典传递给函数体内部。下面是一个示例:

1
2
3
4
5
6
def my_function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")

# 使用关键字参数调用函数
my_function(name="John", age=30, city="New York")

在上面的示例中,my_function 函数定义中的 **kwargs 表示可以接收任意数量的关键字参数。在函数体内部,kwargs 是一个字典,可以使用 items() 方法迭代其中的键值对,并对其进行处理。在函数调用中,传递的关键字参数会被收集到 kwargs 字典中。

运行上述代码,输出将是:

1
2
3
name: John
age: 30
city: New York

通过使用 **kwargs,函数能够接收灵活的关键字参数,并在函数内部以字典的形式进行处理。这使得函数可以处理各种不同的关键字参数,而无需预先指定它们的名称和数量。

源码编安装

  • 源码路径:zjy-190/Software/Python-3.8.3.tgz

  • 安装依赖包

    • apt-get install -y libssl-dev openssl libffi-dev zlib1g-dev
  • 编译安装

    • cd Python-3.8.0
    • ./configure –prefix=/usr/local/python3
    • make && make install
  • pip up

zlib not available 是什么

“zlib not available” 是一个错误消息,通常在使用Python时出现,表示缺少 zlib 模块或库。zlib 是一个用于压缩和解压缩数据的库,通常用于处理压缩文件、网络传输中的数据压缩等。如果您遇到 “zlib not available” 错误,可能是因为您的Python环境没有正确安装或配置 zlib 库。

要解决这个问题,您可以采取以下步骤:

  1. 安装 zlib 开发库:首先,确保您的系统上已经安装了 zlib 开发库。在大多数Linux系统上,可以使用包管理器安装 zlib 开发库,例如:

    • 在Ubuntu上,可以运行以下命令安装 zlib 开发库:

      1
      sudo apt-get install zlib1g-dev
    • 在CentOS上,可以运行以下命令安装 zlib 开发库:

      1
      sudo yum install zlib-devel
    • 在其他Linux发行版上,请使用相应的包管理器安装 zlib 开发库。

  2. 重新编译Python:如果您已经安装了 zlib 开发库但仍然遇到问题,您可能需要重新编译Python,以便它可以正确地链接到 zlib 库。这可以通过以下步骤完成:

    • 下载Python源代码,如果尚未下载。

    • 进入Python源代码的目录。

    • 运行以下命令:

      1
      2
      3
      ./configure
      make
      sudo make install

    这将重新编译Python,并确保它正确链接到 zlib 库。

  3. 检查Python环境:如果您使用的是虚拟环境,请确保虚拟环境中的Python正确配置并链接到 zlib 库。您可以使用以下命令检查虚拟环境的Python版本和 zlib 链接:

    1
    2
    which python
    python -c "import zlib; print(zlib)"

    确保这些命令返回正确的Python解释器和 zlib 模块。

python3 日志处理 工具 推荐

在Python 3中,有许多优秀的日志处理工具可供选择,这些工具可以帮助你有效地记录和管理应用程序的日志信息。以下是一些常用的Python 3日志处理工具的推荐:

  1. Python内置的logging模块:
    Python的标准库中包含了一个内置的logging模块,它提供了强大的日志记录功能。你可以使用这个模块来配置日志级别、输出目标和格式。它是一个常见的选择,因为它是Python的标准库的一部分,无需额外安装。

    1
    2
    3
    import logging

    logging.basicConfig(filename='app.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  2. Loguru:
    Loguru是一个易于使用的第三方日志库,它提供了直观的API和强大的功能。它支持动态日志级别调整、日志旋转、多种输出格式等功能。

    1
    2
    3
    from loguru import logger

    logger.add("app.log", rotation="500 MB", level="INFO")
  3. structlog:
    structlog是一个用于结构化日志记录的库,它允许你轻松地记录自定义字段,并支持多种输出格式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import structlog

    structlog.configure(
    processors=[
    structlog.processors.JSONRenderer(),
    structlog.processors.TimeStamper(fmt="iso"),
    ],
    logger_factory=structlog.PrintLoggerFactory(),
    )
  4. Fluentd:
    Fluentd是一个开源的日志收集和传输工具,它可以集成到Python应用程序中,并将日志发送到不同的目标,如文件、数据库或日志分析工具中。

  5. Loggly、Papertrail等云日志服务:
    如果你的应用程序部署在云上,可以考虑使用云日志服务,如Loggly、Papertrail等。它们提供了强大的日志管理和分析功能,可以帮助你更轻松地处理日志。

选择哪个日志处理工具取决于你的具体需求和偏好。无论你选择哪一个,都应该根据项目的规模和要求来配置和管理日志,以确保你能够有效地监视和调试你的应用程序。

编码

  • 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码
1
# -*- coding: cp-1252 -*-
  • 上述定义允许在源文件中使用 Windows-1252 字符集中的字符编码,对应适合语言为保加利亚语、白俄罗斯语、马其顿语、俄语、塞尔维亚语。

标识符

  • 第一个字符必须是字母表中字母或下划线 _ 。

  • 标识符的其他的部分由字母、数字和下划线组成。

  • 标识符对大小写敏感。

  • 在 Python 3 中,可以用中文作为变量名,非 ASCII 标识符也是允许的了。

python保留字

  • 保留字即关键字,我们不能把它们用作任何标识符名称。Python 的标准库提供了一个 keyword 模块,可以输出当前版本的所有关键字:
    1
    2
    3
    >>> import keyword
    >>> keyword.kwlist
    ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

注释

  • Python中单行注释以 # 开头,实例如下:

    1
    2
    3
    4
    #!/usr/bin/python3

    # 第一个注释
    print ("Hello, Python!") # 第二个注释
  • 多行注释可以用多个 # 号,还有 ‘’’ 和 “””:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/usr/bin/python3

    # 第一个注释
    # 第二个注释

    '''
    第三注释
    第四注释
    '''

    """
    第五注释
    第六注释
    """
    print ("Hello, Python!")

行与缩进

  • python最具特色的就是使用缩进来表示代码块,不需要使用大括号 {}
  • 缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。实例如下
    1
    2
    3
    4
    if True:
    print ("True")
    else:
    print ("False")

多行语句

  • Python 通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠 \ 来实现多行语句,例如:

    1
    2
    3
    total = item_one + \
    item_two + \
    item_three
  • 在 [], {}, 或 () 中的多行语句,不需要使用反斜杠 \,例如:

    1
    2
    total = ['item_one', 'item_two', 'item_three',
    'item_four', 'item_five']

数字(Number)类型

  • python中数字有四种类型:整数、布尔型、浮点数和复数。
    • int (整数), 如 1, 只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。
    • bool (布尔), 如 True。
    • float (浮点数), 如 1.23、3E-2
    • complex (复数), 如 1 + 2j、 1.1 + 2.2j

字符串(String)

  • Python 中单引号 ‘ 和双引号 “ 使用完全相同。
  • 使用三引号(‘’’ 或 “””)可以指定一个多行字符串。
  • 转义符 \。
  • 反斜杠可以用来转义,使用 r 可以让反斜杠不发生转义。 如 r”this is a line with \n” 则 \n 会显示,并不是换行。
  • 按字面意义级联字符串,如 “this “ “is “ “string” 会被自动转换为 this is string。
  • 字符串可以用 + 运算符连接在一起,用 * 运算符重复。
  • Python 中的字符串有两种索引方式,从左往右以 0 开始,从右往左以 -1 开始。
  • Python 中的字符串不能改变。
  • Python 没有单独的字符类型,一个字符就是长度为 1 的字符串。
  • 字符串的截取的语法格式如下:变量[头下标:尾下标:步长]
1
2
3
4
word = '字符串'
sentence = "这是一个句子。"
paragraph = """这是一个段落,
可以由多行组成"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/python3

str='123456789'

print(str) # 输出字符串
print(str[0:-1]) # 输出第一个到倒数第二个的所有字符
print(str[0]) # 输出字符串第一个字符
print(str[2:5]) # 输出从第三个开始到第六个的字符(不包含)
print(str[2:]) # 输出从第三个开始后的所有字符
print(str[1:5:2]) # 输出从第二个开始到第五个且每隔一个的字符(步长为2)
print(str * 2) # 输出字符串两次
print(str + '你好') # 连接字符串

print('------------------------------')

print('hello\nrunoob') # 使用反斜杠(\)+n转义特殊字符
print(r'hello\nrunoob') # 在字符串前面添加一个 r,表示原始字符串,不会发生转义

空行

  • 函数之间或类的方法之间用空行分隔,表示一段新的代码的开始。类和函数入口之间也用一行空行分隔,以突出函数入口的开始
  • 空行与代码缩进不同,空行并不是 Python 语法的一部分。书写时不插入空行,Python 解释器运行也不会出错。但是空行的作用在于分隔两段不同功能或含义的代码,便于日后代码的维护或重构。
    • 空行也是程序代码的一部分。

等待用户输入

  • 执行下面的程序在按回车键后就会等待用户输入:

    1
    2
    3
    #!/usr/bin/python3

    input("\n\n按下 enter 键后退出。")
  • 以上代码中 ,\n\n 在结果输出前会输出两个新的空行。一旦用户按下 enter 键时,程序将退出。

同一行显示多条语句

  • Python 可以在同一行中使用多条语句,语句之间使用分号 ; 分割,以下是一个简单的实例:
    1
    2
    3
    #!/usr/bin/python3

    import sys; x = 'runoob'; sys.stdout.write(x + '\n')

多个语句构成代码组

  • 缩进相同的一组语句构成一个代码块,我们称之代码组
  • 像if、while、def和class这样的复合语句,首行以关键字开始,以冒号( : )结束,该行之后的一行或多行代码构成代码组
  • 我们将首行及后面的代码组称为一个子句(clause)
    1
    2
    3
    4
    5
    6
    if expression : 
    suite
    elif expression :
    suite
    else :
    suite

print 输出

  • print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end=””
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/usr/bin/python3

    x="a"
    y="b"
    # 换行输出
    print( x )
    print( y )

    print('---------')
    # 不换行输出
    print( x, end=" " )
    print( y, end=" " )
    print()

import 与 from…import

  • 在 python 用 import 或者 from…import 来导入相应的模块。
  • 将整个模块(somemodule)导入,格式为: import somemodule
  • 从某个模块中导入某个函数,格式为: from somemodule import somefunction
  • 从某个模块中导入多个函数,格式为: from somemodule import firstfunc, secondfunc, thirdfunc
  • 将某个模块中的全部函数导入,格式为: from somemodule import *
1
2
3
4
5
6
import sys
print('================Python import mode==========================')
print ('命令行参数为:')
for i in sys.argv:
print (i)
print ('\n python 路径为',sys.path)
1
2
3
4
from sys import argv,path  #  导入特定的成员

print('================python from import===================================')
print('path:',path) # 因为已经导入path成员,所以此处引用时不需要加sys.path

基本数据类型

  • Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。
  • 在 Python 中,变量就是变量,它没有类型,我们所说的”类型”是变量所指的内存中对象的类型。
  • 等号(=)用来给变量赋值。
  • 等号(=)运算符左边是一个变量名,等号(=)运算符右边是存储在变量中的值

标准数据类型

  • Python3 中常见的数据类型有:

    • Number(数字)
    • String(字符串)
    • bool(布尔类型)
    • List(列表)
    • Tuple(元组)
    • Set(集合)
    • Dictionary(字典)
  • Python3 的六个标准数据类型中:

    • 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组)
    • 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

数值运算

  • 注:
    1. Python可以同时为多个变量赋值,如a, b = 1, 2。
    2. 一个变量可以通过赋值指向不同类型的对象。
    3. 数值的除法包含两个运算符:/ 返回一个浮点数,// 返回一个整数。
    4. 在混合计算时,Python会把整型转换成为浮点数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 5 + 4  # 加法
9
>>> 4.3 - 2 # 减法
2.3
>>> 3 * 7  # 乘法
21
>>> 2 / 4  # 除法,得到一个浮点数
0.5
>>> 2 // 4 # 除法,得到一个整数
0
>>> 17 % 3 # 取余
2
>>> 2 ** 5 # 乘方
32

List(列表)

  • List(列表) 是 Python 中使用最频繁的数据类型。

  • 列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同,它支持数字,字符串甚至可以包含列表(所谓嵌套)

  • 列表是写在方括号 [] 之间、用逗号分隔开的元素列表。

  • 和字符串一样,列表同样可以被索引和截取,列表被截取后返回一个包含所需元素的新列表

  • 列表截取的语法格式如下:

    • 变量[头下标:尾下标]
  • 注意:

    1. List写在方括号之间,元素用逗号隔开。
    2. 和字符串一样,list可以被索引和切片。
    3. List可以使用+操作符进行拼接。
    4. List中的元素是可以改变的。

Tuple(元组)

  • 元组(tuple)与列表类似,不同之处在于元组的元素不能修改。元组写在小括号 () 里,元素之间用逗号隔开

  • 元组中的元素类型也可以不相同:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/python3

    tuple = ( 'abcd', 786 , 2.23, 'runoob', 70.2  )
    tinytuple = (123, 'runoob')

    print (tuple)             # 输出完整元组
    print (tuple[0])          # 输出元组的第一个元素
    print (tuple[1:3])        # 输出从第二个元素开始到第三个元素
    print (tuple[2:])         # 输出从第三个元素开始的所有元素
    print (tinytuple * 2)     # 输出两次元组
    print (tuple + tinytuple) # 连接元组
  • 注意:

    1. 与字符串一样,元组的元素不能修改。
    2. 元组也可以被索引和切片,方法一样。
    3. 注意构造包含 0 或 1 个元素的元组的特殊语法规则。
    4. 元组也可以使用+操作符进行拼接。

Set(集合)

  • Python 中的集合(Set)是一种无序、可变的数据类型,用于存储唯一的元素。
  • 集合中的元素不会重复,并且可以进行交集、并集、差集等常见的集合操作
  • 在 Python 中,集合使用大括号 {} 表示,元素之间用逗号 , 分隔
  • 另外,也可以使用 set() 函数创建集合
  • 注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
  • 创建格式:
    1
    2
    3
    parame = {value01,value02,...}
    或者
    set(value)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/python3

sites = {'Google', 'Taobao', 'Runoob', 'Facebook', 'Zhihu', 'Baidu'}

print(sites)   # 输出集合,重复的元素被自动去掉

# 成员测试
if 'Runoob' in sites :
    print('Runoob 在集合中')
else :
    print('Runoob 不在集合中')


# set可以进行集合运算
a = set('abracadabra')
b = set('alacazam')

print(a)

print(a - b)     # a 和 b 的差集

print(a | b)     # a 和 b 的并集

print(a & b)     # a 和 b 的交集

print(a ^ b)     # a 和 b 中不同时存在的元素

Dictionary(字典)

  • 字典(dictionary)是Python中另一个非常有用的内置数据类型
  • 列表是有序的对象集合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。
  • 字典是一种映射类型,字典用 { } 标识,它是一个无序的 键(key) : 值(value) 的集合
  • 键(key)必须使用不可变类型。
  • 在同一个字典中,键(key)必须是唯一的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/python3

dict = {}
dict['one'] = "1 - 菜鸟教程"
dict[2]     = "2 - 菜鸟工具"

tinydict = {'name': 'runoob','code':1, 'site': 'www.runoob.com'}


print (dict['one'])       # 输出键为 'one' 的值
print (dict[2])           # 输出键为 2 的值
print (tinydict)          # 输出完整的字典
print (tinydict.keys())   # 输出所有键
print (tinydict.values()) # 输出所有值
  • 构造函数 dict() 可以直接从键值对序列中构建字典如下:

    1
    2
    3
    4
    5
    6
    >>> dict([('Runoob', 1), ('Google', 2), ('Taobao', 3)])
    {'Runoob': 1, 'Google': 2, 'Taobao': 3}
    >>> {x: x**2 for x in (2, 4, 6)}
    {2: 4, 4: 16, 6: 36}
    >>> dict(Runoob=1, Google=2, Taobao=3)
    {'Runoob': 1, 'Google': 2, 'Taobao': 3}
  • 字典类型也有一些内置的函数,例如 clear()、keys()、values() 等。

  • 注意:

    1. 字典是一种映射类型,它的元素是键值对。
    2. 字典的关键字必须为不可变类型,且不能重复。
    3. 创建空字典使用 { }

bytes类型

  • 在 Python3 中,bytes 类型表示的是不可变的二进制序列(byte sequence)。

  • 与字符串类型不同的是,bytes 类型中的元素是整数值(0 到 255 之间的整数),而不是 Unicode 字符。

  • bytes 类型通常用于处理二进制数据,比如图像文件、音频文件、视频文件等等。在网络编程中,也经常使用 bytes 类型来传输二进制数据。

  • 创建 bytes 对象的方式有多种,最常见的方式是使用 b 前缀:

  • 此外,也可以使用 bytes() 函数将其他类型的对象转换为 bytes 类型。bytes() 函数的第一个参数是要转换的对象,第二个参数是编码方式,如果省略第二个参数,则默认使用 UTF-8 编码:

    1
    x = bytes("hello", encoding="utf-8")
  • 与字符串类型类似,bytes 类型也支持许多操作和方法,如切片、拼接、查找、替换等等。同时,由于 bytes 类型是不可变的,因此在进行修改操作时需要创建一个新的 bytes 对象。例如:

    1
    2
    3
    x = b"hello"
    y = x[1:3]  # 切片操作,得到 b"el"
    z = x + b"world"  # 拼接操作,得到 b"helloworld"

逻辑运算符

  • Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:

  • and : x and y

    • 布尔”与” - 如果 x 为 False,x and y 返回 x 的值,否则返回 y 的计算值。
    • (a and b) 返回 20。
  • or : x or y

    • 布尔”或” - 如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。
    • (a or b) 返回 10。
  • not : not x

    • 布尔”非” - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。
    • not(a and b) 返回 False

成员运算符

  • 除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组

  • in

    • 如果在指定的序列中找到值返回 True,否则返回 False。
    • x 在 y 序列中 , 如果 x 在 y 序列中返回 True。
  • not in

    • 如果在指定的序列中没有找到值返回 True,否则返回 False。
    • x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。

身份运算符

  • 身份运算符用于比较两个对象的存储单元

  • is

    • is 是判断两个标识符是不是引用自一个对象
    • x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False
  • is not

    • is not 是判断两个标识符是不是引用自不同对象
    • x is not y , 类似 id(x) != id(y)。如果引用的不是同一个对象则返回结果 True,否则返回 False。

if语句

  • Python中if语句的一般形式如下所示:

    1
    2
    3
    4
    5
    6
    if condition_1:
    statement_block_1
    elif condition_2:
    statement_block_2
    else:
    statement_block_3
  • Python 中用 elif 代替了 else if,所以if语句的关键字为:if – elif – else。

  • 注意:

    1. 每个条件后面要使用冒号 :,表示接下来是满足条件后要执行的语句块。
    2. 使用缩进来划分语句块,相同缩进数的语句在一起组成一个语句块。
    3. 在 Python 中没有 switch…case 语句,但在 Python3.10 版本添加了 match…case,功能也类似

match…case

  • Python 3.10 增加了 match…case 的条件判断,不需要再使用一连串的 if-else 来判断了

  • match 后的对象会依次与 case 后的内容进行匹配,如果匹配成功,则执行匹配到的表达式,否则直接跳过,_ 可以匹配一切。

  • 语法格式如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    match subject:
    case <pattern_1>:
    <action_1>
    case <pattern_2>:
    <action_2>
    case <pattern_3>:
    <action_3>
    case _:
    <action_wildcard>
  • case _: 类似于 C 和 Java 中的 default:,当其他 case 都无法匹配时,匹配这条,保证永远会匹配成功。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def http_error(status):
        match status:
            case 400:
                return "Bad request"
            case 404:
                return "Not found"
            case 418:
                return "I'm a teapot"
            case _:
                return "Something's wrong with the internet"

    mystatus=400
    print(http_error(400))

while循环

  • Python 中 while 语句的一般形式:

    1
    2
    while 判断条件(condition):
    执行语句(statements)……
  • 同样需要注意冒号和缩进。另外,在 Python 中没有 do..while 循环。

  • 以下实例使用了 while 来计算 1 到 100 的总和:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/env python3

    n = 100

    sum = 0
    counter = 1
    while counter <= n:
    sum = sum + counter
    counter += 1

    print("1 到 %d 之和为: %d" % (n,sum))
  • 无限循环

    • 我们可以通过设置条件表达式永远不为 false 来实现无限循环,实例如下:
      1
      2
      3
      4
      5
      6
      7
      8
      #!/usr/bin/python3

      var = 1
      while var == 1 : # 表达式永远为 true
      num = int(input("输入一个数字 :"))
      print ("你输入的数字是: ", num)

      print ("Good bye!")
  • while 循环使用 else 语句

    • 如果 while 后面的条件语句为 false 时,则执行 else 的语句块。
    • 语法格式如下:
      1
      2
      3
      4
      while <expr>:
      <statement(s)>
      else:
      <additional_statement(s)>
  • expr 条件语句为 true 则执行 statement(s) 语句块,如果为 false,则执行 additional_statement(s)。

for 语句

  • Python for 循环可以遍历任何可迭代对象,如一个列表或者一个字符串

  • for循环的一般格式如下:

    1
    2
    3
    4
    for <variable> in <sequence>:
    <statements>
    else:
    <statements>
  • 在 Python 中,for…else 语句用于在循环结束后执行一段代码。

    1
    2
    3
    4
    for item in iterable:
    # 循环主体
    else:
    # 循环结束后执行的代码
  • 当循环执行完毕(即遍历完 iterable 中的所有元素)后,会执行 else 子句中的代码,如果在循环过程中遇到了 break 语句,则会中断循环,此时不会执行 else 子句。

range()函数

  • 如果你需要遍历数字序列,可以使用内置 range() 函数。它会生成数列

break 和 continue 语句及循环中的 else 子句

  • break 语句可以跳出 for 和 while 的循环体。如果你从 for 或 while 循环中终止,任何对应的循环 else 块将不执行。
  • continue 语句被用来告诉 Python 跳过当前循环块中的剩余语句,然后继续进行下一轮循环。

pass 语句

  • Python pass是空语句,是为了保持程序结构的完整性。
  • pass 不做任何事情,一般用做占位语句,如下实例
    1
    2
    >>>while True:
    ... pass # 等待键盘中断 (Ctrl+C)

end 关键字

  • 关键字end可以用于将结果输出到同一行,或者在输出的末尾添加不同的字符,实例如下:
    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/python3

    # Fibonacci series: 斐波纳契数列
    # 两个元素的总和确定了下一个数
    a, b = 0, 1
    while b < 1000:
    print(b, end=',')
    a, b = b, a+b

推导式

  • Python 推导式是一种独特的数据处理方式,可以从一个数据序列构建另一个新的数据序列的结构体。
  • Python 支持各种数据结构的推导式:
    • 列表(list)推导式
    • 字典(dict)推导式
    • 集合(set)推导式
    • 元组(tuple)推导式

列表推导式

  • 列表推导式格式为:

    1
    2
    3
    4
    5
    6
    7
    [表达式 for 变量 in 列表] 
    [out_exp_res for out_exp in input_list]

    或者

    [表达式 for 变量 in 列表 if 条件]
    [out_exp_res for out_exp in input_list if condition]
  • out_exp_res:列表生成元素表达式,可以是有返回值的函数。

  • for out_exp in input_list:迭代 input_list 将 out_exp 传入到 out_exp_res 表达式中。

  • if condition:条件语句,可以过滤列表中不符合条件的值。

字典推导式

  • 字典推导基本格式:
    1
    2
    3
    4
    5
    { key_expr: value_expr for value in collection }



    { key_expr: value_expr for value in collection if condition }

集合推导式

  • 集合推导式基本格式:
    1
    2
    3
    { expression for item in Sequence }

    { expression for item in Sequence if conditional }

元组推导式(生成器表达式)

  • 元组推导式可以利用 range 区间、元组、列表、字典和集合等数据类型,快速生成一个满足指定需求的元组

  • 元组推导式基本格式:

    1
    2
    3
    (expression for item in Sequence )

    (expression for item in Sequence if conditional )
  • 元组推导式和列表推导式的用法也完全相同,只是元组推导式是用 () 圆括号将各部分括起来,而列表推导式用的是中括号 [],另外元组推导式返回的结果是一个生成器对象

迭代器与生成器

迭代器

  • 迭代是 Python 最强大的功能之一,是访问集合元素的一种方式。
  • 迭代器是一个可以记住遍历的位置的对象。
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
  • 迭代器有两个基本的方法:iter() 和 next()。

生成器

  • 在 Python 中,使用了 yield 的函数被称为生成器(generator)。
  • yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
  • 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
  • 当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。
  • 然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。
  • 调用一个生成器函数,返回的是一个迭代器对象

函数

  • 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

  • 函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数

  • 你可以定义一个由自己想要功能的函数,以下是简单的规则:

    • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
    • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
    • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
    • 函数内容以冒号 : 起始,并且缩进。
    • return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
  • Python 定义函数使用 def 关键字,一般格式如下:

    1
    2
    def 函数名(参数列表):
    函数体
  • 定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。

  • 这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行

参数传递

  • 在 python 中,类型属于对象,对象有不同类型的区分,变量是没有类型的:
    1
    2
    3
    a=[1,2,3]

    a="Runoob"
  • 以上代码中,[1,2,3] 是 List 类型,”Runoob” 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象

可更改(mutable)与不可更改(immutable)对象

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。

  • 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

  • python 函数的参数传递:

    • 不可变类型:类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
    • 可变类型:类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
  • python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象

参数

  • 以下是调用函数时可使用的正式参数类型:
    • 必需参数
    • 关键字参数
    • 默认参数
    • 不定长参数

必需参数

  • 必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
  • 调用 printme() 函数,你必须传入一个参数,不然会出现语法错误:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/python3

    #可写函数说明
    def printme( str ):
    "打印任何传入的字符串"
    print (str)
    return

    # 调用 printme 函数,不加参数会报错
    printme()

关键字参数

  • 关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
  • 使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
  • 以下实例在函数 printme() 调用时使用参数名:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/python3

    #可写函数说明
    def printme( str ):
    "打印任何传入的字符串"
    print (str)
    return

    #调用printme函数
    printme( str = "菜鸟教程")

默认参数

  • 调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/usr/bin/python3

    #可写函数说明
    def printinfo( name, age = 35 ):
    "打印任何传入的字符串"
    print ("名字: ", name)
    print ("年龄: ", age)
    return

    #调用printinfo函数
    printinfo( age=50, name="runoob" )
    print ("------------------------")
    printinfo( name="runoob" )

不定长参数

  • 你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名。基本语法如下:

    1
    2
    3
    4
    def functionname([formal_args,] *var_args_tuple ):
    "函数_文档字符串"
    function_suite
    return [expression]
  • 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/python3

    # 可写函数说明
    def printinfo( arg1, *vartuple ):
    "打印任何传入的参数"
    print ("输出: ")
    print (arg1)
    print (vartuple)

    # 调用printinfo 函数
    printinfo( 70, 60, 50 )

匿名函数

  • Python 使用 lambda 来创建匿名函数。
  • 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
    • lambda 只是一个表达式,函数体比 def 简单很多。
    • lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
    • lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
    • 虽然 lambda 函数看起来只能写一行,却不等同于 C 或 C++ 的内联函数,内联函数的目的是调用小函数时不占用栈内存从而减少函数调用的开销,提高代码的执行速度。

语法

  • lambda 函数的语法只包含一个语句,如下:

    1
    lambda [arg1 [,arg2,.....argn]]:expression
  • 设置参数 a 加上 10:

    1
    2
    x = lambda a : a + 10
    print(x(5))
  • 我们可以将匿名函数封装在一个函数内,这样可以使用同样的代码来创建多个匿名函数。

  • 以下实例将匿名函数封装在 myfunc 函数中,通过传入不同的参数来创建不同的匿名函数:

    1
    2
    3
    4
    5
    6
    7
    8
    def myfunc(n):
    return lambda a : a * n

    mydoubler = myfunc(2)
    mytripler = myfunc(3)

    print(mydoubler(11))
    print(mytripler(11))

return 语句

  • return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。之前的例子都没有示范如何返回数值,以下实例演示了 return 语句的用法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/usr/bin/python3

    # 可写函数说明
    def sum( arg1, arg2 ):
    # 返回2个参数的和."
    total = arg1 + arg2
    print ("函数内 : ", total)
    return total

    # 调用sum函数
    total = sum( 10, 20 )
    print ("函数外 : ", total)

强制位置参数

  • Python3.8 新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。

  • 在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 和 f 要求为关键字形参:

    1
    2
    def f(a, b, /, c, d, *, e, f):
    print(a, b, c, d, e, f)
  • 以下使用方法是正确的:

    1
    f(10, 20, 30, d=40, e=50, f=60)
  • 以下使用方法会发生错误:

    1
    2
    f(10, b=20, c=30, d=40, e=50, f=60)   # b 不能使用关键字参数的形式
    f(10, 20, 30, 40, 50, f=60) # e 必须使用关键字参数的形式

模块

  • 在前面的几个章节中我们基本上是用 python 解释器来编程,如果你从 Python 解释器退出再进入,那么你定义的所有的方法和变量就都消失了。
  • 为此 Python 提供了一个办法,把这些定义存放在文件中,为一些脚本或者交互式的解释器实例使用,这个文件被称为模块。
  • 模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 python 标准库的方法。

import 语句

  • 想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:

    1
    import module1[, module2[,... moduleN]
  • 当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。

  • 搜索路径是一个解释器会先进行搜索的所有目录的列表。如想要导入模块 support,需要把命令放在脚本的顶端:

    1
    2
    3
    4
    5
    6
    #!/usr/bin/python3
    # Filename: support.py

    def print_func( par ):
    print ("Hello : ", par)
    return

from … import 语句

  • Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:
    1
    from modname import name1[, name2[, ... nameN]]

from … import * 语句

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

name 属性

  • 一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。

    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/python3
    # Filename: using_name.py

    if __name__ == '__main__':
    print('程序自身在运行')
    else:
    print('我来自另一模块')
  • 每个模块都有一个__name__属性,当其值是’main‘时,表明该模块自身在运行,否则是被引入。

  • namemain 底下是双下划线, _ _ 是这样去掉中间的那个空格。

dir() 函数

  • 内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    >>> import fibo, sys
    >>> dir(fibo)
    ['__name__', 'fib', 'fib2']
    >>> dir(sys)
    ['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
    '__package__', '__stderr__', '__stdin__', '__stdout__',
    '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
    '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
    'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
    'call_tracing', 'callstats', 'copyright', 'displayhook',
    'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
    'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
    'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
    'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
    'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
    'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
    'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
    'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
    'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
    'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
    'thread_info', 'version', 'version_info', 'warnoptions']
  • 如果没有给定参数,那么 dir() 函数会罗列出当前定义的所有名称:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    >>> a = [1, 2, 3, 4, 5]
    >>> import fibo
    >>> fib = fibo.fib
    >>> dir() # 得到一个当前模块中定义的属性列表
    ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
    >>> a = 5 # 建立一个新的变量 'a'
    >>> dir()
    ['__builtins__', '__doc__', '__name__', 'a', 'sys']
    >>>
    >>> del a # 删除变量名a
    >>>
    >>> dir()
    ['__builtins__', '__doc__', '__name__', 'sys']
    >>>

标准模块

  • Python 本身带着一些标准的模块库,在 Python 库参考文档中将会介绍到(就是后面的”库参考文档”)。
  • 有些模块直接被构建在解析器里,这些虽然不是一些语言内置的功能,但是他却能很高效的使用,甚至是系统级调用也没问题。
  • 这些组件会根据不同的操作系统进行不同形式的配置,比如 winreg 这个模块就只会提供给 Windows 系统。
  • 应该注意到这有一个特别的模块 sys ,它内置在每一个 Python 解析器中。变量 sys.ps1 和 sys.ps2 定义了主提示符和副提示符所对应的字符串:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> import sys
    >>> sys.ps1
    '>>> '
    >>> sys.ps2
    '... '
    >>> sys.ps1 = 'C> '
    C> print('Runoob!')
    Runoob!
    C>

  • 包是一种管理 Python 模块命名空间的形式,采用”点模块名称”。

  • 比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。

  • 就好像使用模块的时候,你不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。

  • 这样不同的作者都可以提供 NumPy 模块,或者是 Python 图形库。

  • 不妨假设你想设计一套统一处理声音文件和数据的模块(或者称之为一个”包”)。

  • 现存很多种不同的音频文件格式(基本上都是通过后缀名区分的,例如: .wav,:file:.aiff,:file:.au,),所以你需要有一组不断增加的模块,用来在不同的格式之间转换。

  • 并且针对这些音频数据,还有很多不同的操作(比如混音,添加回声,增加均衡器功能,创建人造立体声效果),所以你还需要一组怎么也写不完的模块来处理这些操作。

  • 这里给出了一种可能的包结构(在分层的文件系统中):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    sound/                          顶层包
    __init__.py 初始化 sound 包
    formats/ 文件格式转换子包
    __init__.py
    wavread.py
    wavwrite.py
    aiffread.py
    aiffwrite.py
    auread.py
    auwrite.py
    ...
    effects/ 声音效果子包
    __init__.py
    echo.py
    surround.py
    reverse.py
    ...
    filters/ filters 子包
    __init__.py
    equalizer.py
    vocoder.py
    karaoke.py
    ...
  • 在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录。

  • 目录只有包含一个叫做 init.py 的文件才会被认作是一个包,主要是为了避免一些滥俗的名字(比如叫做 string)不小心的影响搜索路径中的有效模块。

  • 最简单的情况,放一个空的 :file:init.py就可以了。当然这个文件中也可以包含一些初始化代码或者为(将在后面介绍的) __all__变量赋值。

  • 用户可以每次只导入一个包里面的特定模块,比如:

    1
    import sound.effects.echo
  • 这将会导入子模块:sound.effects.echo。 他必须使用全名去访问:

    1
    sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
  • 还有一种导入子模块的方法是:

    1
    from sound.effects import echo
  • 这同样会导入子模块: echo,并且他不需要那些冗长的前缀,所以他可以这样使用:

    1
    echo.echofilter(input, output, delay=0.7, atten=4)
  • 还有一种变化就是直接导入一个函数或者变量:

    1
    from sound.effects.echo import echofilter
  • 同样的,这种方法会导入子模块: echo,并且可以直接使用他的 echofilter() 函数:

    1
    echofilter(input, output, delay=0.7, atten=4)
  • 注意当使用 from package import item 这种形式的时候,对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。

  • import 语法会首先把 item 当作一个包定义的名称,如果没找到,再试图按照一个模块去导入。如果还没找到,抛出一个 :exc:ImportError 异常。

  • 反之,如果使用形如 import item.subitem.subsubitem 这种导入形式,除了最后一项,都必须是包,而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字。

输入输出

输出格式美化

  • Python两种输出值的方式: 表达式语句和 print() 函数。
  • 第三种方式是使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用。
  • 如果你希望输出的形式更加多样,可以使用 str.format() 函数来格式化输出值。
  • 如果你希望将输出的值转成字符串,可以使用 repr() 或 str() 函数来实现。
    • str(): 函数返回一个用户易读的表达形式。
    • repr(): 产生一个解释器易读的表达形式。

旧式字符串格式化

  • % 操作符也可以实现字符串格式化。 它将左边的参数作为类似 sprintf() 式的格式化字符串, 而将右边的代入, 然后返回格式化后的字符串. 例如:

    1
    2
    3
    >>> import math
    >>> print('常量 PI 的值近似为:%5.3f。' % math.pi)
    常量 PI 的值近似为:3.142
  • 因为 str.format() 是比较新的函数, 大多数的 Python 代码仍然使用 % 操作符。但是因为这种旧式的格式化最终会从该语言中移除, 应该更多的使用 str.format().

读取键盘输入

  • Python 提供了 input() 内置函数从标准输入读入一行文本,默认的标准输入是键盘。
    1
    2
    3
    4
    #!/usr/bin/python3

    str = input("请输入:")
    print ("你输入的内容是: ", str)

读和写文件

  • open() 将会返回一个 file 对象,基本语法格式如下:

    1
    open(filename, mode)
    • filename:包含了你要访问的文件名称的字符串值。
    • mode:决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
  • 以下实例将字符串写入到文件 foo.txt 中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/usr/bin/python3

    # 打开一个文件
    f = open("/tmp/foo.txt", "w")

    f.write( "Python 是一个非常好的语言。\n是的,的确非常好!!\n" )

    # 关闭打开的文件
    f.close()
    • 第一个参数为要打开的文件名。
    • 第二个参数描述文件如何使用的字符。 mode 可以是 ‘r’ 如果文件只读, ‘w’ 只用于写 (如果存在同名文件则将被删除), 和 ‘a’ 用于追加文件内容; 所写的任何数据都会被自动增加到末尾. ‘r+’ 同时用于读写。 mode 参数是可选的; ‘r’ 将是默认值。

文件对象的方法

  • 本节中剩下的例子假设已经创建了一个称为 f 的文件对象。

  • f.read()

  • 为了读取一个文件的内容,调用 f.read(size), 这将读取一定数目的数据, 然后作为字符串或字节对象返回。

  • size 是一个可选的数字类型的参数。 当 size 被忽略了或者为负, 那么该文件的所有内容都将被读取并且返回。

  • 以下实例假定文件 foo.txt 已存在(上面实例中已创建):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/python3

    # 打开一个文件
    f = open("/tmp/foo.txt", "r")

    str = f.read()
    print(str)

    # 关闭打开的文件
    f.close()
  • f.readline()

  • f.readline() 会从文件中读取单独的一行。换行符为 ‘\n’。f.readline() 如果返回一个空字符串, 说明已经已经读取到最后一行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/python3

    # 打开一个文件
    f = open("/tmp/foo.txt", "r")

    str = f.readline()
    print(str)

    # 关闭打开的文件
    f.close()
  • f.readlines()

  • f.readlines() 将返回该文件中包含的所有行。

  • 如果设置可选参数 sizehint, 则读取指定长度的字节, 并且将这些字节按行分割。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/python3

    # 打开一个文件
    f = open("/tmp/foo.txt", "r")

    str = f.readlines()
    print(str)

    # 关闭打开的文件
    f.close()
  • f.write()

  • f.write(string) 将 string 写入到文件中, 然后返回写入的字符数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/usr/bin/python3

    # 打开一个文件
    f = open("/tmp/foo.txt", "w")

    num = f.write( "Python 是一个非常好的语言。\n是的,的确非常好!!\n" )
    print(num)
    # 关闭打开的文件
    f.close()
  • f.tell()

  • f.tell() 返回文件对象当前所处的位置, 它是从文件开头开始算起的字节数。

  • f.seek()

  • 如果要改变文件指针当前的位置, 可以使用 f.seek(offset, from_what) 函数。

  • from_what 的值, 如果是 0 表示开头, 如果是 1 表示当前位置, 2 表示文件的结尾,例如:

    • seek(x,0) : 从起始位置即文件首行首字符开始移动 x 个字符
    • seek(x,1) : 表示从当前位置往后移动x个字符
    • seek(-x,2):表示从文件的结尾往前移动x个字符
  • from_what 值为默认为0,即文件开头。下面给出一个完整的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> f = open('/tmp/foo.txt', 'rb+')
    >>> f.write(b'0123456789abcdef')
    16
    >>> f.seek(5)     # 移动到文件的第六个字节
    5
    >>> f.read(1)
    b'5'
    >>> f.seek(-3, 2) # 移动到文件的倒数第三字节
    13
    >>> f.read(1)
    b'd'
  • f.close()

  • 在文本文件中 (那些打开文件的模式下没有 b 的), 只会相对于文件起始位置进行定位。

  • 当你处理完一个文件后, 调用 f.close() 来关闭文件并释放系统的资源,如果尝试再调用该文件,则会抛出异常。

    1
    2
    3
    4
    5
    >>> f.close()
    >>> f.read()
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ValueError: I/O operation on closed file
  • 当处理一个文件对象时, 使用 with 关键字是非常好的方式。在结束后, 它会帮你正确的关闭文件。 而且写起来也比 try - finally 语句块要简短:

    1
    2
    3
    4
    >>> with open('/tmp/foo.txt', 'r') as f:
    ...     read_data = f.read()
    >>> f.closed
    True

pickle 模块

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

  • 通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储。

  • 通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

  • 基本接口:

    1
    pickle.dump(obj, file, [,protocol])

python3 OS 文件/目录 方法

  • os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:
    序号 方法及描述
    1
    os.access(path, mode)

检验权限模式
2
os.chdir(path)

改变当前工作目录
3
os.chflags(path, flags)

设置路径的标记为数字标记。
4
os.chmod(path, mode)

更改权限
5
os.chown(path, uid, gid)

更改文件所有者
6
os.chroot(path)

改变当前进程的根目录
7
os.close(fd)

关闭文件描述符 fd
8
os.closerange(fd_low, fd_high)

关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略
9
os.dup(fd)

复制文件描述符 fd
10
os.dup2(fd, fd2)

将一个文件描述符 fd 复制到另一个 fd2
11
os.fchdir(fd)

通过文件描述符改变当前工作目录
12
os.fchmod(fd, mode)

改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。
13
os.fchown(fd, uid, gid)

修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。
14
os.fdatasync(fd)

强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。
15
os.fdopen(fd[, mode[, bufsize]])

通过文件描述符 fd 创建一个文件对象,并返回这个文件对象
16
os.fpathconf(fd, name)

返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。
17
os.fstat(fd)

返回文件描述符fd的状态,像stat()。
18
os.fstatvfs(fd)

返回包含文件描述符fd的文件的文件系统的信息,Python 3.3 相等于 statvfs()。
19
os.fsync(fd)

强制将文件描述符为fd的文件写入硬盘。
20
os.ftruncate(fd, length)

裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。
21
os.getcwd()

返回当前工作目录
22
os.getcwdb()

返回一个当前工作目录的Unicode对象
23
os.isatty(fd)

如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。
24
os.lchflags(path, flags)

设置路径的标记为数字标记,类似 chflags(),但是没有软链接
25
os.lchmod(path, mode)

修改连接文件权限
26
os.lchown(path, uid, gid)

更改文件所有者,类似 chown,但是不追踪链接。
27
os.link(src, dst)

创建硬链接,名为参数 dst,指向参数 src
28
os.listdir(path)

返回path指定的文件夹包含的文件或文件夹的名字的列表。
29
os.lseek(fd, pos, how)

设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效
30
os.lstat(path)

像stat(),但是没有软链接
31
os.major(device)

从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。
32
os.makedev(major, minor)

以major和minor设备号组成一个原始设备号
33
os.makedirs(path[, mode])

递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。
34
os.minor(device)

从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。
35
os.mkdir(path[, mode])

以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。
36
os.mkfifo(path[, mode])

创建命名管道,mode 为数字,默认为 0666 (八进制)
37
os.mknod(filename[, mode=0600, device])
创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。

38
os.open(file, flags[, mode])

打开一个文件,并且设置需要的打开选项,mode参数是可选的
39
os.openpty()

打开一个新的伪终端对。返回 pty 和 tty的文件描述符。
40
os.pathconf(path, name)

返回相关文件的系统配置信息。
41
os.pipe()

创建一个管道. 返回一对文件描述符(r, w) 分别为读和写
42
os.popen(command[, mode[, bufsize]])

从一个 command 打开一个管道
43
os.read(fd, n)

从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。
44
os.readlink(path)

返回软链接所指向的文件
45
os.remove(path)

删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。
46
os.removedirs(path)

递归删除目录。
47
os.rename(src, dst)

重命名文件或目录,从 src 到 dst
48
os.renames(old, new)

递归地对目录进行更名,也可以对文件进行更名。
49
os.rmdir(path)

删除path指定的空目录,如果目录非空,则抛出一个OSError异常。
50
os.stat(path)

获取path指定的路径的信息,功能等同于C API中的stat()系统调用。
51
os.stat_float_times([newvalue])
决定stat_result是否以float对象显示时间戳

52
os.statvfs(path)

获取指定路径的文件系统统计信息
53
os.symlink(src, dst)

创建一个软链接
54
os.tcgetpgrp(fd)

返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组
55
os.tcsetpgrp(fd, pg)

设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。
56
os.tempnam([dir[, prefix]])

Python3 中已删除。返回唯一的路径名用于创建临时文件。
57
os.tmpfile()

Python3 中已删除。返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。
58
os.tmpnam()

Python3 中已删除。为创建一个临时文件返回一个唯一的路径
59
os.ttyname(fd)

返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。
60
os.unlink(path)

删除文件路径
61
os.utime(path, times)

返回指定的path文件的访问和修改的时间。
62
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])

输出在文件夹中的文件名通过在树中游走,向上或者向下。
63
os.write(fd, str)

写入字符串到文件描述符 fd中. 返回实际写入的字符串长度
64
os.path 模块

获取文件的属性信息。
65
os.pardir()

获取当前目录的父目录,以字符串形式显示目录名。
66
os.replace()

重命名文件或目录。

错误和异常

  • Python 有两种错误很容易辨认:语法错误和异常。
  • Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常。

异常

  • 即便 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常。
  • 错误信息的前面部分显示了异常发生的上下文,并以调用栈的形式显示具体信息

异常处理 try/except

  • try 语句按照如下方式工作;

    • 首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)。
    • 如果没有异常发生,忽略 except 子句,try 子句执行后结束。
    • 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。
    • 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。
  • 一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行

  • 处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。

  • 一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组

try/except…else

  • try/except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后

  • else 子句将在 try 子句没有发生任何异常的时候执行。

try-finally 语句

  • try-finally 语句无论是否发生异常都将执行最后的代码。

抛出异常

  • Python 使用 raise 语句抛出一个指定的异常。

  • raise语法格式如下:

    1
    raise [Exception [, args [, traceback]]]
  • raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。

  • 如果你只想知道这是否抛出了一个异常,并不想去处理它,那么一个简单的 raise 语句就可以再次把它抛出

用户自定义异常

  • 你可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception 类,可以直接继承,或者间接继承,例如:

定义清理行为

  • try 语句还有另外一个可选的子句,它定义了无论在任何情况下都会执行的清理行为。 例如:

预定义的清理行为

  • 一些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行

简介

  • redis相关笔记

ubuntu apt 命令安装

  • 在 Ubuntu 系统安装 Redis 可以使用以下命令:

    1
    2
    sudo apt update
    sudo apt install redis-server
  • 启动 Redis

    1
    redis-server
  • 查看 redis 是否启动?

    1
    redis-cli
  • 以上命令将打开以下终端:

    1
    redis 127.0.0.1:6379>
  • 127.0.0.1 是本机 IP ,6379 是 redis 服务端口。现在我们输入 PING 命令。

    1
    2
    redis 127.0.0.1:6379> ping
    PONG
  • 以上说明我们已经成功安装了redis。

Redis配置

Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf(Windows 名为 redis.windows.conf)。

你可以通过 CONFIG 命令查看或设置配置项。

  • 语法

    • Redis CONFIG 命令格式如下:
      1
      redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME
    • 示例
      1
      2
      3
      4
      redis 127.0.0.1:6379> CONFIG GET loglevel

      1) "loglevel"
      2) "notice"
    • 使用 * 号获取所有配置项:
  • 编辑配置

    • 你可以通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。
    • CONFIG SET 命令基本语法:
      1
      redis 127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
    • 实例
      1
      2
      3
      4
      5
      6
      redis 127.0.0.1:6379> CONFIG SET loglevel "notice"
      OK
      redis 127.0.0.1:6379> CONFIG GET loglevel

      1) "loglevel"
      2) "notice"

Redis 数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

  • String(字符串)

    • string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
    • string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
    • string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
    • 实例
      1
      2
      3
      4
      redis 127.0.0.1:6379> SET runoob "菜鸟教程"
      OK
      redis 127.0.0.1:6379> GET runoob
      "菜鸟教程"
    • 在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 runoob,对应的值为 菜鸟教程。
    • 注意:一个键最大能存储 512MB。
  • Hash(哈希)

    • Redis hash 是一个键值(key=>value)对集合。
    • Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
    • 实例
      1
      2
      3
      4
      5
      6
      7
      redis 127.0.0.1:6379> DEL runoob
      redis 127.0.0.1:6379> HMSET runoob field1 "Hello" field2 "World"
      "OK"
      redis 127.0.0.1:6379> HGET runoob field1
      "Hello"
      redis 127.0.0.1:6379> HGET runoob field2
      "World"
    • 实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value
  • List(列表)

    • Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
    • 实例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      redis 127.0.0.1:6379> DEL runoob
      redis 127.0.0.1:6379> lpush runoob redis
      (integer) 1
      redis 127.0.0.1:6379> lpush runoob mongodb
      (integer) 2
      redis 127.0.0.1:6379> lpush runoob rabbitmq
      (integer) 3
      redis 127.0.0.1:6379> lrange runoob 0 10
      1) "rabbitmq"
      2) "mongodb"
      3) "redis"
      redis 127.0.0.1:6379>
  • Set(集合)

    • Redis 的 Set 是 string 类型的无序集合。
    • 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
    • sadd 命令
      • 添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。
      • sadd key member
    • 实例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      redis 127.0.0.1:6379> DEL runoob
      redis 127.0.0.1:6379> sadd runoob redis
      (integer) 1
      redis 127.0.0.1:6379> sadd runoob mongodb
      (integer) 1
      redis 127.0.0.1:6379> sadd runoob rabbitmq
      (integer) 1
      redis 127.0.0.1:6379> sadd runoob rabbitmq
      (integer) 0
      redis 127.0.0.1:6379> smembers runoob

      1) "redis"
      2) "rabbitmq"
      3) "mongodb"
    • 注意:以上实例中 rabbitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。
  • zset(sorted set:有序集合)

    • Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
    • 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序
    • zset的成员是唯一的,但分数(score)却可以重复。
    • zadd 命令
      • 添加元素到集合,元素在集合中存在则更新对应score
      • zadd key score member
    • 实例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      redis 127.0.0.1:6379> DEL runoob
      redis 127.0.0.1:6379> zadd runoob 0 redis
      (integer) 1
      redis 127.0.0.1:6379> zadd runoob 0 mongodb
      (integer) 1
      redis 127.0.0.1:6379> zadd runoob 0 rabbitmq
      (integer) 1
      redis 127.0.0.1:6379> zadd runoob 0 rabbitmq
      (integer) 0
      redis 127.0.0.1:6379> ZRANGEBYSCORE runoob 0 1000
      1) "mongodb"
      2) "rabbitmq"
      3) "redis"

简介

  • PCL(Point Cloud Library)常用的编程技巧

pcl::PointCloudpcl::PointXYZ对象怎么转为pcl::PointCloudpcl::PointXYZ::Ptr 指针

pcl::PointCloud<pcl::PointXYZ> 对象转换为 pcl::PointCloud<pcl::PointXYZ>::Ptr 指针可以通过以下几种方法实现,具体取决于您希望如何进行转换。这里提供了两种常用的方法:

  1. 使用 boost::make_shared(或 std::make_shared

    您可以使用 boost::make_shared 或 C++11 中的 std::make_shared 来创建一个智能指针,并将其指向现有的 pcl::PointCloud<pcl::PointXYZ> 对象。这种方法非常简洁,因为它利用了智能指针的构造函数,而无需手动进行分配和释放。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <pcl/point_cloud.h>
    #include <pcl/point_types.h>
    #include <boost/make_shared.hpp> // 或者 #include <memory>(C++11)

    int main()
    {
    pcl::PointCloud<pcl::PointXYZ> cloud; // 假设已经有一个点云对象

    // 使用 boost::make_shared(或 std::make_shared)进行转换
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPtr = boost::make_shared<pcl::PointCloud<pcl::PointXYZ>>(cloud);

    // 使用 cloudPtr 进行操作

    return 0;
    }
  2. 使用显式赋值

    另一种方法是通过显式赋值创建指针并将其指向现有的 pcl::PointCloud<pcl::PointXYZ> 对象。这种方法需要手动进行指针的分配和释放。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <pcl/point_cloud.h>
    #include <pcl/point_types.h>

    int main()
    {
    pcl::PointCloud<pcl::PointXYZ> cloud; // 假设已经有一个点云对象

    // 创建指针并赋值
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPtr(new pcl::PointCloud<pcl::PointXYZ>(cloud));

    // 使用 cloudPtr 进行操作

    return 0;
    }

这两种方法都能将现有的 pcl::PointCloud<pcl::PointXYZ> 对象转换为 pcl::PointCloud<pcl::PointXYZ>::Ptr 指针。您可以根据您的代码风格和需求选择其中之一。需要注意的是,在任何情况下,确保在不再需要智能指针时正确释放内存,以避免内存泄漏。

vtkDebugLeaksManager 定义

vtkDebugLeaksManager 是 Visualization Toolkit(VTK)库中的一个类,用于在调试和测试过程中检测内存泄漏。VTK 是一个用于处理和可视化科学和工程数据的开源软件系统。它提供了广泛的功能,包括图形渲染、图像处理、体积可视化、几何建模等,常用于科学计算、医学图像处理和工程仿真等领域。

vtkDebugLeaksManager 类主要用于在程序执行过程中跟踪 VTK 对象的创建和销毁,以帮助开发者发现是否有未释放的内存资源。它通常在开发和测试阶段使用,因为在正式发布的代码中,应该尽量避免内存泄漏。

该类的定义和使用可以在 VTK 的源代码中找到,下面是一个可能的伪代码示例,演示了它的基本用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <vtkDebugLeaksManager.h>

int main() {
// 启用内存泄漏检测
vtkDebugLeaksManager::GetInstance()->SetDebugLeaks(true);

// ... 创建和使用 VTK 对象 ...

// 在程序结束前,析构 VTK 对象

// 输出内存泄漏信息
vtkDebugLeaksManager::GetInstance()->DumpLeaks(std::cerr);

// 禁用内存泄漏检测
vtkDebugLeaksManager::GetInstance()->SetDebugLeaks(false);

return 0;
}

请注意,上述示例是伪代码,实际的使用方式可能会有所不同,具体取决于你所编写的代码和项目的需求。如果你正在使用 VTK 并且想要了解更多关于 vtkDebugLeaksManager 类的详细信息,建议查阅 VTK 的官方文档或源代码。

简介

  • pytorch框架

Python pytorch 是什么

PyTorch 是一个用于深度学习的开源机器学习库,由Facebook的人工智能研究小组开发。它提供了一个灵活而直观的深度学习开发平台,支持动态计算图,这使得模型的定义和训练更加直观和灵活。

以下是 PyTorch 的一些主要特点:

  1. 动态计算图: PyTorch 使用动态计算图,这意味着计算图是在运行时构建的。这使得模型的定义更加灵活,方便调试和动态修改模型结构。

  2. 张量操作: PyTorch 提供了一个名为 torch.Tensor 的多维数组对象,支持丰富的张量操作。张量是 PyTorch 中用于表示数据的核心数据结构。

  3. 自动微分: PyTorch 自带了自动微分系统,称为 Autograd。它能够自动计算张量上的梯度,这对于训练神经网络和优化模型参数非常有用。

  4. 模块化设计: PyTorch 的模块化设计使得构建和训练复杂的深度学习模型变得更加简单。你可以通过组合不同的模块来构建自己的模型。

  5. 丰富的生态系统: PyTorch 生态系统包含了许多用于深度学习的工具和库,包括 TorchVision(用于计算机视觉任务的库)、TorchText(用于文本处理的库)等。

  6. 易用性: PyTorch 的 API 设计注重用户友好性,其接口简单而直观,使得新手和专业人士都能够轻松上手。

使用 PyTorch,你可以构建、训练和部署各种深度学习模型,包括卷积神经网络(CNN)、循环神经网络(RNN)、变换器(Transformer)等。由于其灵活性和易用性,PyTorch 在学术界和工业界都广泛应用。

Python pytorch库 详解

PyTorch是一个用于深度学习的开源机器学习库,它提供了一个灵活而直观的深度学习开发平台。以下是对PyTorch库的一些详细解释:

  1. torch.Tensor: torch.Tensor 是PyTorch的核心数据结构,用于表示多维数组。它支持各种数学运算,具有自动微分功能,允许用户轻松地计算梯度。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import torch

    # 创建一个张量
    x = torch.tensor([[1, 2, 3], [4, 5, 6]])

    # 加法操作
    y = x + 2

    # 自动微分
    y.backward()
  2. torch.nn: torch.nn 模块提供了用于构建神经网络的类和函数。用户可以通过继承torch.nn.Module创建自定义的神经网络模型,并使用各种层(如线性层、卷积层、循环层等)构建模型。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import torch
    import torch.nn as nn

    class SimpleModel(nn.Module):
    def __init__(self):
    super(SimpleModel, self).__init__()
    self.fc = nn.Linear(10, 5)

    def forward(self, x):
    return self.fc(x)

    model = SimpleModel()
  3. torch.optim: torch.optim 模块提供了各种优化算法,例如SGD、Adam、RMSprop等,用于优化模型的参数。用户可以选择适合自己问题的优化器。例如:

    1
    2
    3
    import torch.optim as optim

    optimizer = optim.SGD(model.parameters(), lr=0.01)
  4. torch.autograd: torch.autograd 模块提供了自动微分的功能,用于计算梯度。通过使用requires_grad=True的张量,PyTorch可以追踪相关的计算,并生成计算图,从而计算梯度。例如:

    1
    2
    3
    4
    5
    6
    import torch

    x = torch.tensor([2.0], requires_grad=True)
    y = x ** 2
    y.backward()
    print(x.grad)
  5. torch.utils.data: torch.utils.data 模块提供了用于数据处理和加载的工具,包括DatasetDataLoader。用户可以自定义数据集,然后使用DataLoader来加载批量数据。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    import torch
    from torch.utils.data import Dataset, DataLoader

    class CustomDataset(Dataset):
    # 定义自己的数据集

    dataset = CustomDataset()
    dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
  6. torchvision: torchvision 库提供了用于计算机视觉任务的工具和数据集。其中包括常用的数据集、模型和图像转换函数。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import torchvision.transforms as transforms
    from torchvision.datasets import CIFAR10
    from torch.utils.data import DataLoader

    transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ])

    dataset = CIFAR10(root='./data', train=True, download=True, transform=transform)
    dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

这只是 PyTorch 库中的一部分功能,它提供了许多其他工具和库,以支持广泛的深度学习任务。详细的文档和示例可以在 PyTorch 的官方网站上找到。

简介

  • ultralytics库

Python ultralytics 是什么

Ultralytics 是一个开源的深度学习工具库,专注于计算机视觉任务。它为研究人员和开发者提供了一系列用于训练、评估和部署深度学习模型的工具和实用程序。Ultralytics 最为人熟知的是其与目标检测、语义分割和其他计算机视觉任务相关的支持。

Ultralytics 提供了一个名为 YOLOv5(You Only Look Once,版本 5)的目标检测框架,这是一个快速且高效的实时目标检测算法。YOLOv5 是在 PyTorch 中实现的,并通过 Ultralytics 提供的工具进行训练和部署。

以下是 Ultralytics 的一些主要特点:

  1. YOLOv5 框架: Ultralytics 提供了 YOLOv5 的实现,支持目标检测任务。YOLOv5 是一种单阶段目标检测算法,具有较快的推理速度和较好的准确性。

  2. 简化的训练流程: Ultralytics 提供了简化的训练流程,使得用户能够轻松地使用自己的数据集进行模型训练。通过简单的配置文件,用户可以指定数据集、模型架构、超参数等信息。

  3. 全面的评估工具: Ultralytics 提供了丰富的评估工具,用于评估模型在不同任务上的性能。这包括目标检测、语义分割等任务。

  4. 模型导出和部署: Ultralytics 支持将训练好的模型导出为 TorchScript 格式,以便在不同平台上进行部署。这使得用户能够在移动设备、边缘设备等环境中使用训练好的模型。

  5. 实时监控和可视化: Ultralytics 提供了实时的训练监控和结果可视化工具,方便用户实时了解模型的训练进度和性能。

要使用 Ultralytics,你可以通过其 GitHub 仓库(https://github.com/ultralytics/yolov5)获取源代码和文档,了解详细的使用说明和示例。请注意,Ultralytics 的主要重点是目标检测任务,如果你有其他计算机视觉任务的需求,可能需要考虑其他专注于该任务的工具库。

Python ultralytics 详解

截至我的知识截止日期(2022年1月),Ultralytics提供了YOLOv5(You Only Look Once,版本5)的实现,是一个用于计算机视觉目标检测的开源库。以下是关于Ultralytics YOLOv5的一些详细信息:

  1. YOLOv5模型: YOLOv5是一种目标检测算法,其特点是在单个前向传播中直接预测图像中的多个边界框及其对应的类别概率。YOLOv5相对于先前版本做了一些改进,包括更高的性能、更好的准确性和更灵活的训练流程。

  2. 模型架构: YOLOv5的架构包括骨干网络(Backbone)、特征金字塔网络(Feature Pyramid Network,FPN)、锚点框(Anchor Boxes)等组件。这些组件的组合使得模型能够有效地检测各种尺度和形状的目标。

  3. 训练流程: Ultralytics提供了一个简单的训练流程,用户可以通过配置文件指定训练参数、数据集路径、模型架构等。训练脚本会加载配置并开始训练过程。用户可以使用自己的数据集进行训练,同时Ultralytics也提供了一些标准的计算机视觉数据集的支持。

  4. 评估工具: Ultralytics提供了全面的评估工具,用户可以使用这些工具评估训练好的模型在测试集上的性能。评估包括计算各种指标,如精度、召回率、F1分数等。

  5. 部署支持: Ultralytics支持将训练好的模型导出为TorchScript格式,这使得用户能够在不同平台上进行模型部署。这对于将模型部署到嵌入式设备或生产环境中是非常有用的。

  6. 实时监控和可视化: Ultralytics提供了实时监控工具,用户可以实时查看模型在训练过程中的性能。此外,Ultralytics还提供了可视化工具,帮助用户直观地理解模型的预测结果。

如果你想深入了解Ultralytics YOLOv5的使用和详细信息,建议查阅官方文档和GitHub仓库。请注意,软件库的更新可能会导致信息的变更,因此建议查看最新版本的文档。

python3 安装ultralytics库

目前(截至我的知识截止日期2022年1月),Ultralytics库是专为YOLOv5目标检测框架设计的,它提供了用于训练、评估和部署YOLOv5模型的工具和实用程序。下面是安装Ultralytics库的步骤:

使用 pip 安装:

1
pip install -U ultralytics

这将会安装最新版本的Ultralytics库。请确保你的Python环境已经安装了pip,如果没有,你需要首先安装pip。

使用源代码安装:

你也可以从Ultralytics的GitHub仓库中获取源代码并安装:

1
2
3
git clone https://github.com/ultralytics/yolov5.git
cd yolov5
pip install -U -r requirements.txt

请注意,Ultralytics库对其他一些Python库有依赖关系,因此你可能需要先安装这些依赖。上述命令中的requirements.txt文件列出了这些依赖项。

注意事项:

  1. Ultralytics库可能会更新,因此建议定期检查其GitHub仓库以获取最新版本和文档。

  2. 我的回答基于2022年1月的信息,版本和依赖关系可能发生变化。请查看Ultralytics的GitHub仓库和文档以获取最新的安装说明和使用说明。

  3. 如果你的Python环境有多个版本,请确保你使用的是正确的Python版本(通常是Python 3.x)。

希望这能帮助你成功安装Ultralytics库。

简介

  • zmq库中常用的函数

C++ zmq::socket_t::set()函数 详解

在 ZeroMQ 的 C++ 绑定中,zmq::socket_t::set() 函数用于设置套接字选项。它允许你在运行时修改 ZeroMQ 套接字的行为,以满足特定的需求。这个函数的签名通常是这样的:

1
2
template<typename T>
socket_t& set(zmq::sockopt::opt<T> option, const T& value);

其中,option 是一个枚举类型,表示要设置的选项,value 是相应选项的值。

下面是一些常用的套接字选项以及它们的用途:

  1. ZMQ_SUBSCRIBE/ZMQ_UNSUBSCRIBE:用于设置订阅的消息过滤器。在订阅者套接字上调用 set() 函数并传递 ZMQ_SUBSCRIBE 选项可以指定要订阅的消息前缀,而 ZMQ_UNSUBSCRIBE 用于取消订阅。

  2. ZMQ_LINGER:设置套接字关闭时等待未发送消息的时间。如果未设置,套接字在关闭时将立即丢弃未发送的消息。可以通过设置这个选项来等待一段时间,以确保消息被发送。

  3. ZMQ_SNDHWM/ZMQ_RCVHWM:设置套接字的发送和接收高水位标记。当队列中的消息数量达到这个水位标记时,后续的发送操作将被阻塞(发送者)或丢弃(接收者)。

  4. ZMQ_SNDTIMEO/ZMQ_RCVTIMEO:设置发送和接收操作的超时时间。当设置了这个选项后,发送和接收操作将在超时时间内等待,如果超时则返回错误。

  5. ZMQ_TCP_KEEPALIVE/ZMQ_TCP_KEEPALIVE_CNT/ZMQ_TCP_KEEPALIVE_IDLE/ZMQ_TCP_KEEPALIVE_INTVL:用于设置 TCP 连接的保持活动参数。

  6. ZMQ_ROUTER_MANDATORY:在 ROUTER 套接字上设置此选项,如果无法路由消息,则立即报告错误。

等等。

需要注意的是,不是所有的选项都适用于所有类型的套接字,而且某些选项的行为可能因 ZeroMQ 版本而异。因此,在使用 set() 函数设置选项时,建议参考 ZeroMQ 文档和版本说明以确保选项的行为符合预期。

zmq::socket_t::set() 函数

  • 这个函数是zmq::socket_t的父类zmq::socket_base中的成员函数,其函数声明为

    1
    2
    3
    4
    5
    6
    7
    // Set array socket option, e.g.
    // `socket.set(zmq::sockopt::plain_username, "foo123")`
    template<int Opt, int NullTerm>
    void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
    {
    set_option(Opt, buf, std::strlen(buf));
    }
  • 其中,第一个参数是一个枚举值,用来表示该连接的属性,其值如下

    • zmq::sockopt::subscribe
  • 第二个参数是字符串,用来标记该连接

简介

  • Tornado框架相关笔记

Tornado是什么

  • Python3 Tornado是一个基于Python语言的异步网络框架,它可以用于编写高性能的Web服务器和Web应用程序。Tornado的主要特点是其非阻塞的I/O模型,使得它在处理大量并发连接时能够表现出色。它也被广泛用于实时Web服务、长连接应用和WebSocket等场景。

python3 Tornado详解

Python的Tornado框架是一个强大的异步网络库,它专注于高性能和可伸缩性。下面是对Tornado的一些详细解释:

  1. 异步IO:Tornado采用了异步的I/O模型,使用非阻塞的事件循环来处理并发连接。这意味着它可以在不同的客户端连接之间快速切换,而不会阻塞整个进程。

  2. Web框架:Tornado提供了一个简单而灵活的Web框架,可以用于构建Web应用程序。它包含了路由、请求处理器、模板引擎等功能,使得开发Web应用变得更加容易。

  3. 异步HTTP客户端和服务器:除了作为Web框架,Tornado还提供了异步的HTTP客户端和服务器,可以用于构建各种类型的网络应用,包括代理、爬虫等。

  4. WebSocket支持:Tornado支持WebSocket协议,这使得它可以用于构建实时的Web应用,如聊天应用、实时数据展示等。

  5. 协程支持:Tornado支持使用Python的协程来编写异步代码,这使得编写异步程序更加简单和直观。

  6. 性能优化:Tornado在设计上注重性能和可伸缩性,它的事件循环机制和非阻塞IO可以有效地处理大量的并发连接,使得应用程序可以轻松地应对高负载的情况。

总的来说,Tornado是一个功能丰富且性能出色的异步网络库,适用于构建各种类型的网络应用。

python3 Tornado安装

安装 Tornado 可以通过 pip 工具来完成。如果你已经安装了 Python3 和 pip,只需在命令行中运行以下命令:

1
pip install tornado

这会自动下载并安装 Tornado 及其依赖项。安装完成后,你就可以在 Python 中使用 Tornado 框架了。

python3 Tornado 示例

以下是一个简单的Python 3 Tornado示例,演示了如何创建一个简单的Web服务器,监听端口并返回 “Hello, World!” 消息给客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, World!")

def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])

if __name__ == "__main__":
app = make_app()
app.listen(8888)
print("Server is running at http://localhost:8888")
tornado.ioloop.IOLoop.current().start()

在这个示例中,我们首先导入了Tornado的必要模块。然后,我们定义了一个名为MainHandler的请求处理器类,它继承自tornado.web.RequestHandler。在MainHandler类中,我们定义了一个get()方法来处理HTTP GET请求,并使用self.write()方法向客户端返回 “Hello, World!” 消息。

接着,我们定义了一个make_app()函数来创建Tornado应用程序对象。在这个函数中,我们通过tornado.web.Application类来创建一个应用程序实例,并指定了一个URL路由映射,将”/“路径映射到MainHandler类。

最后,在if __name__ == "__main__":块中,我们创建了应用程序对象,并通过app.listen()方法指定了服务器监听的端口(在这里是8888)。然后,我们启动了Tornado的事件循环,使得服务器可以一直运行并监听来自客户端的HTTP请求。

你可以运行这个示例代码,然后在浏览器中访问”http://localhost:8888",就会看到 “Hello, World!” 消息返回给你。

简介

  • python中常用的技巧

python3 获取当前路径

在 Python3 中,可以使用标准库模块 ospathlib 来获取当前路径。以下是两种方式的详细用法:


方法一:使用 os 模块

1. 获取当前工作目录(运行脚本时所在的目录)

1
2
3
4
import os

current_path = os.getcwd()
print("当前工作目录是:", current_path)

2. 获取当前脚本文件所在的目录

1
2
3
4
import os

script_dir = os.path.dirname(os.path.abspath(__file__))
print("当前脚本所在目录是:", script_dir)

方法二:使用 pathlib 模块

pathlib 是从 Python 3.4 开始引入的模块,用于处理文件和路径,功能更强大且代码更简洁。

1. 获取当前工作目录

1
2
3
4
from pathlib import Path

current_path = Path.cwd()
print("当前工作目录是:", current_path)

2. 获取当前脚本文件所在的目录

1
2
3
4
from pathlib import Path

script_dir = Path(__file__).resolve().parent
print("当前脚本所在目录是:", script_dir)

两者的区别

  1. os.getcwd()Path.cwd() 获取的是工作目录(运行脚本时的目录),与脚本文件本身的存储路径无关。
  2. os.path.dirname(os.path.abspath(__file__))Path(__file__).resolve().parent 获取的是脚本文件的实际存储路径。

如果你运行脚本时,工作目录和脚本文件目录不一致,需要特别注意选择合适的方法。

python 执行scp命令

在 Python 中执行 SCP 命令可以使用 paramiko 库,这是一个用于SSH2的Python库,支持SSH会话和文件传输。以下是一个示例,演示如何使用 paramiko 实现在 Python 中执行 SCP 命令:

首先,确保你已经安装了 paramiko 库。如果没有安装,你可以使用 pip 来安装它:

1
pip install paramiko

接下来,以下是一个简单的 Python 示例代码,演示如何使用 paramiko 执行 SCP 命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import paramiko

# 连接 SSH 服务器
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.connect('your_server_ip', username='your_username', password='your_password')

# 执行 SCP 命令,将本地文件复制到远程服务器
local_path = '/path/to/local/file.txt'
remote_path = '/path/to/remote/file.txt'

# 使用 SCPClient 实现文件传输
scp = ssh.open_scp()
scp.put(local_path, remote_path) # 本地文件复制到远程服务器
scp.close()

# 关闭 SSH 连接
ssh.close()

上述代码中的 your_server_ip 是远程服务器的 IP 地址,your_username 是用于 SSH 登录的用户名,your_password 是对应的密码。local_path 是本地文件的路径,remote_path 是远程服务器上的目标路径。

这个示例展示了如何使用 paramiko 库创建一个 SSH 连接并使用 SCP 在本地和远程服务器之间传输文件。根据你的实际情况,你可能需要更改相应的路径和凭据信息。

简介

  • zmq通讯组件相关理论基础

概述

  • mq,是消息队列(message queue)的简称,目前有多种消息队列可用,包括RabbitMQ、Kafka等,它们各有特色,可以结合具体的项目需求使用。
  • ZeroMQ简称Zmq,或者0mq,核心引擎由c++编写,是轻量级消息通信库,在对传统的标准socket接口扩展的基础上形成的特色消息通信中间件。
  • Zmq提供了异步消息队列的抽象,具有多种消息通信模式,能够实现消息过滤,能够无缝对接多种传输协议。
  • 简言之,使用socket时,需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZMQ屏 蔽了这些细节,让网络编程更简单
  • ZeroMQ是网络通信中新的一层,介于应用层和传输层之间(按照TCP/IP划分),是一个可伸缩层,可并行运行,分散在分布式系统间。
  • 官方描述
    • ZMQ(?MQ、ZeroMQ, 0MQ)看起来像是一套嵌入式的网络链接库,但工作起来更像是一个并发式的框架。它提供的套接字可以在多种协议中传输消息,如线程间、进程间、TCP、广播等。你可以使用套接字构建多对多的连接模式,如扇出、发布-订阅、任务分发、请求-应答等。ZMQ的快速足以胜任集群应用产品。它的异步I/O机制让你能够构建多核应用程序,完成异步消息处理任务。ZMQ有着多语言支持,并能在几乎所有的操作系统上运行。
  • ZMQ是iMatix公司的产品,以LGPLv3开源协议发布。

为什么要使用ZMQ

  • 当今的许多应用程序都包含了跨越某种网络的组件,无论这种网络是局域网还是互联网。因此,许多应用程序开发者最终都会处理某种类型的消息传递

  • 一些开发人员使用消息队列产品,但大多数时候,他们使用TCP或UDP自己做。

  • 这些协议并不难用,但是,​从 A 发送几个字节到 B 和以任何一种可靠的方式处理消息,这两者之间有很大的区别。

  • 让我们来看看当开始使用原始的TCP连接部件的时候,我们要面对的典型问题。任何可复用的消息层都需要解决如下所有这些问题或其中的大部分问题:

    • 我们如何处理I/O呢?
      • ​是让我们的应用程序阻塞,还是在后台处理I/O呢?这是一个关键的设计决策。阻塞式I/O 创建的架构不能很好地扩展,但后台I/O 也是非常难以正确做到的
    • 我们如何处理动态组件(例如,暂时撤除的块)呢?​
      • 我们需要正式将组件划分为“客户端”和“服务器”,并强制该服务器不能撤除吗?那么,如果我们想将服务器连接到服务器时该怎么办呢?我们需要每隔几秒钟就尝试重新连接吗?.
    • ​我们如何表示在线路上的消息呢?​
      • 我们应该怎样将数据组织为帧,才能使得它很容易写入和读取,避免缓冲区溢出,既对小型消息高效,也足以处理非常大的戴着聚会礼帽的跳舞猫的视频呢?
    • ​我们如何处理不能立即传递的消息呢?
      • ​特别是当我们在等待一个组件的联机回应时如何处理呢?我们需要丢弃消息,把它们放入一个数据库,或者把它们放到一个内存队列吗?
    • 我们在哪里存储消息队列呢?​
      • 如果组件从队列中读取很慢,导致我们的队列堆积,这会发生什么情况?我们的策略是什么呢?
    • 我们如何处理丢失的消息呢?
      • ​我们应该等待新的数据,要求重发,还是应该建立某种可靠性层,确保信息不会丢失呢?如果该层本身崩溃了该怎么办呢?
    • 如果我们需要使用一个不同的网络传输,比如说,用多播来取代TCP 单播,或IPv6,该怎么办呢?​我们需要重写应用程序吗?还是将传输抽象到某个层中呢?
    • 我们如何路由消息呢?​我们可以发送同样的消息到多个接收者吗?我们可以发送应答给原来的请求者吗?
    • 我们如何编写出另一种语言的API 呢?
      • ​我们应该重新实现一个线路级协议,还是重新包装一个库?如果是前者,我们怎么能保证协议栈的高效稳定呢?如果是后者,我们又怎么能保证互操作性呢?
    • ​我们应该如何表示数据,以便它可以在不同的架构之间读取呢?​我们应该对数据类型强制执行特定的编码吗?究竟到什么程度,才是消息传递系统的工作,而不是更高一层的工作呢?
    • ​我们应该如何处理网络错误呢?​是等待并重试,默默地忽略它们,还是终止它们呢?
  • ​ZeroMQ解决传统网络编程的问题:

    • 调用的socket接口较多。
    • TCP是一对一的连接。
    • 编程需要关注很多socket细节问题。
    • 不支持跨平台编程。
    • 需要自行处理分包、组包问题。
    • 流式传输时需处理粘包、半包问题。
    • 需自行处理网络异常,比如连接异常中断、重连等。
    • 服务端和客户端启动有先后。
    • 自行处理IO模型。
    • 自行实现消息的缓存。
    • 自行实现对消息的加密。

依赖环境

  • libzmq3-dev, libzmq5
  • libzmqpp-dev, libzmqpp4

客户端-服务器模式(Client-server)

  • 客户机-服务器模式用于允许一个ZMQ_SERVER服务器与一个或多个ZMQ_CLIENT客户机通信。客户端总是启动对话,之后任何一方都可以向另一方异步发送消息

ZMQ_CLIENT

  • ZMQ_CLIENT套接字与ZMQ_SERVER套接字通信。任何一个对等点都可以连接,但是通常推荐的模型是绑定ZMQ_SERVER并连接ZMQ_CLIENT。

  • 如果ZMQ_CLIENT套接字已经建立了连接,zmq_send()将接受消息,将它们排成队列,并在网络允许的情况下尽可能快地发送它们。传出缓冲区限制由套接字的高水位标志定义。如果传出缓冲区已满,或者没有连接的对等点,zmq_send()将默认阻塞。ZMQ_CLIENT套接字不会删除消息。

  • 当ZMQ_CLIENT套接字连接到多个ZMQ_SERVER套接字时,发送出去的消息将在连接的对等端之间循环分发。同样,ZMQ_CLIENT套接字公平地从每个连接的对等端接收消息。这种用法仅适用于无状态协议。

  • ZMQ_CLIENT套接字是线程安全的,可以从多个线程同时使用。注意,来自ZMQ_SERVER套接字的响应将发送到调用zmq_msg_recv()的第一个客户机线程。如果需要获得对原始线程的响应,每个线程使用一个ZMQ_CLIENT套接字。

  • ZMQ_CLIENT套接字是线程安全的。它们在发送时不接受ZMQ_SNDMORE选项,而在接收时不接受ZMQ_RCVMORE。这就限制了他们只能使用单个部件的数据。其目的是扩展API以允许分散/收集多部分数据。

  • ZMQ_CLIENT特性摘要 

    • 兼容的对等套接字ZMQ_SERVER方向双向的发送/接收模式无限制外发路由策略扇出(Fan out)入网路由策略公平排队静音状态下的操作阻塞

ZMQ_SERVER

  • ZMQ_SERVER套接字与一组ZMQ_CLIENT套接字通信。ZMQ_SERVER套接字只能应答传入消息:ZMQ_CLIENT对等端必须始终发起对话。

  • 每个接收到的消息都有一个routing_id,它是一个32位无符号整数。应用程序可以使用zmq_msg_routing_id(3)来获取它。要向给定的ZMQ_CLIENT对等点发送消息,应用程序必须使用zmq_msg_set_routing_id(3)在消息上设置对等点的routing_id。

  • 如果没有指定routing_id,或者没有引用已连接的客户端对等点,则发送调用将在EHOSTUNREACH中失败。如果客户端对等端的传出缓冲区已满,发送调用将阻塞,除非在发送中使用ZMQ_DONT_WAIT,在这种情况下,它将通过EAGAIN失败。ZMQ_SERVER套接字在任何情况下都不应该丢失消息。

  • ZMQ_SERVER套接字是线程安全的。它们在发送时不接受ZMQ_SNDMORE选项,而在接收时不接受ZMQ_RCVMORE。这就限制了他们只能使用单个部件的数据。其目的是扩展API以允许分散/收集多部分数据。

  • ZMQ_SERVER特性摘要 

    • 兼容的对等套接字ZMQ_CLIENT方向双向的发送/接收模式无限制外发路由策略扇出(Fan out)入网路由策略公平排队静音状态下的操作返回EAGAIN

其他

  • API参考文档:http://api.zeromq.org/master:_start

简介

  • zmq通讯组件相关理论基础知识

维基百科 zmq

  • zmq(ZeroMQ)是一个为可伸缩的分布式或并发应用程序设计的高性能异步消息库。它提供一个消息队列, 但是与面向消息的中间件不同,ZeroMQ的运行不需要专门的消息代理(message broker)。该库设计成常见的套接字风格的API

  • ZeroMQ是由iMatix公司和大量贡献者组成的社群共同开发的。ZeroQ通过许多第三方软件支持大部分流行的编程语言,从Java和Python到Erlang和Haskell

  • ZMQ的技术

    • 类库提供一些套接字(对传统Berkeley套接字和Unix domain socket的泛化),每一个套接字可以代表一个端口之间的多对多连接。以消息的粒度进行操作,套接字需要使用一种消息模式(message pattern),然后专门为那种模式进行了优化。
  • 基本的ZeroMQ模式有:

    • 请求响应模式,将一组客户端连接到一组服务器。这是一种远程过程调用和任务分发模式
    • 发布/订阅模式,将一组发布者连接到一组订阅者。这是一种数据分发模式。
    • 管道模式,以扇出/扇入模式连接节点,可以有多个步骤,可以有循环。这是一种并行的任务分发和收集模式。
    • 排他对模式,在一个排他对中连接两个套接字。 (这是一种高级的为某种用例而设计的低级别模式)
  • 任何通过套接字的消息被看作不透明的数据块。发送给订阅者的消息可以自动地通过块最开始的字符串进行过滤。ZeroMQ提供多种消息传输协议,包括TCP,PGM(可靠的多播),进程间通信(IPC) 以及线程间通讯(ITC)。

  • 由于内部线程模型,ZeroMQ的性能非常好,通过利用一种自动消息批处理技术,它甚至在吞吐量上超过了TCP的性能。

  • ZeroMQ实现了ZMTP, ZeroMQ消息传输协议。[4] ZMTP定义了向后兼容性的规则,可扩展的安全机制,命令和消息分帧,连接元数据,以及其他传输层功能。不使用完整的ZeroMQ实现,而是直接实现ZMTP协议的项目不断增加。

C++ zmq是什么

C++ zmq 是指 ZeroMQ 的 C++ 绑定。ZeroMQ 是一个高性能、异步消息传递库,用于在分布式系统中实现消息通信。它提供了简单而强大的 API,允许开发者构建各种通信模式,包括请求-应答、发布-订阅、推送-拉取等。

C++ zmq 库提供了 ZeroMQ 的 C++ API,使得在 C++ 应用程序中使用 ZeroMQ 变得更加方便。通过 C++ zmq,你可以利用 ZeroMQ 的功能来构建分布式系统,实现各种消息传递模式,并且可以在不同的平台上进行部署。

ZeroMQ 的设计理念是简单易用,同时保持高性能和灵活性,因此它在许多项目中被广泛使用,包括大规模分布式系统、实时数据处理系统、消息队列等场景。C++ zmq 的出现进一步促进了 ZeroMQ 在 C++ 生态系统中的应用和普及。

C++ zmq库 详解

C++ zmq 是 ZeroMQ 的 C++ 绑定,允许你在 C++ 应用程序中使用 ZeroMQ 的功能。ZeroMQ 是一个轻量级的消息传递库,用于构建分布式和并发系统。下面是 C++ zmq 库的一些详细解释:

  1. 简单而强大的 API:C++ zmq 提供了简单而直观的 API,使得在 C++ 应用程序中使用 ZeroMQ 变得容易。它的设计目标之一是简化消息传递的复杂性,因此 API 设计得非常易于理解和使用。

  2. 支持各种通信模式:ZeroMQ 支持多种通信模式,包括请求-应答、发布-订阅、推送-拉取等。C++ zmq 库允许你利用这些通信模式来构建不同类型的分布式系统,根据需要进行灵活的通信。

  3. 高性能和低延迟:ZeroMQ 被设计为高性能和低延迟的消息传递库。C++ zmq 库继承了这些特性,在 C++ 应用程序中实现了高效的消息传递,适用于需要快速响应和高吞吐量的场景。

  4. 跨平台支持:C++ zmq 库支持多种操作系统,包括 Linux、Windows 和 macOS,使得你可以在不同的平台上部署和运行你的应用程序。

  5. 灵活性和可扩展性:ZeroMQ 的设计具有很高的灵活性和可扩展性,允许你根据应用程序的需要定制通信模式和传输协议。C++ zmq 提供了丰富的配置选项,使得你可以根据需求进行定制。

  6. 社区活跃:ZeroMQ 是一个开源项目,拥有活跃的社区支持和持续的更新。C++ zmq 库也得到了广泛的使用和贡献,因此可以在社区中找到丰富的资源和支持。

总的来说,C++ zmq 是一个强大而灵活的库,适用于构建各种类型的分布式系统和消息传递应用程序。它提供了简单易用的 API、高性能的消息传递、跨平台支持等特性,使得在 C++ 应用程序中实现分布式通信变得更加容易和高效。

简介

  • 备战2024年5月份软件设计师的考试,备考周期为一个半月。

初步学习计划

  • 快速看完一遍视频教程,目的是为了掌握考试的方向和学习的方向
  • 刷题,在看课程的同时刷题,目的是为了高效率的学习,仅看视频是意义不大的。

简介

  • Hexo 框架的基础知识

在文章中插入图片

  • 绝对路径本地引用
    • 当Hexo项目中只用到少量图片时,可以将图片统一放在 source/images文件夹中,通过markdown的语法访问它们
  • 图片引用示例

Hexo使用NexT主题设置主页显示文章摘要方法

方法一:在文章中使用
Read more »

简介

  • hugo 框架相关的理论基础知识

hugo框架 详解

Hugo是一个用于构建静态网站的开源网站生成器。它以速度和性能为重点,是一个非常受欢迎的静态网站生成器,特别适用于博客、文档和小型到中型网站的构建。下面是对Hugo框架的详细解释:

  1. 静态网站生成器:Hugo是一个静态网站生成器,意味着它不需要动态服务器或数据库来生成网页。它将Markdown、HTML、CSS、JavaScript等源文件转换为静态HTML文件,这些文件可以轻松地托管在各种Web服务器上,因此不需要服务器端的处理。

  2. 速度和性能:Hugo以速度和性能为特点。它被设计为非常快速的生成器,允许在几秒钟内生成大型网站。这是因为Hugo是用Go编写的,Go是一门高性能的编程语言。

  3. 单一二进制文件:Hugo被构建为一个单一的二进制文件,因此安装非常简单。你不需要安装大量依赖或复杂的配置,只需下载适用于你的操作系统的Hugo二进制文件,然后开始使用它。

  4. 主题系统:Hugo支持主题,你可以轻松地更改网站的外观和样式。有许多免费和付费的Hugo主题可供选择,或者你可以创建自己的主题。

  5. Markdown支持:Hugo主要使用Markdown格式来编写内容,这使得创建和编辑网站内容非常容易,因为Markdown语法简单直观。

  6. 数据驱动:Hugo采用数据驱动的方法,允许你创建各种类型的内容,例如博客文章、页面、菜单等。你可以使用前端数据文件来定义站点内容。

  7. 自定义内容类型:Hugo允许你定义自己的内容类型,这意味着你可以创建适合特定需求的内容结构,如项目、事件、产品等。

  8. 多语言支持:Hugo支持多语言站点,允许你轻松创建多语言的网站,每个语言版本都可以有自己的内容。

  9. 自动部署支持:Hugo与各种部署工具(如Netlify、GitHub Pages等)集成得很好,这使得将生成的静态文件部署到互联网上变得容易。

  10. 活跃的社区:Hugo有一个活跃的开发社区,提供了丰富的文档、主题和插件。如果你遇到问题,可以在社区中找到帮助。

总的来说,Hugo是一个强大的静态网站生成器,适用于个人博客、小型企业网站、文档站点等。它的速度、性能和灵活性使其成为一个受欢迎的选择,特别是对于那些寻求简单、高效的网站构建解决方案的人。

hugo框架 安装教程 详解

Hugo是一个强大的静态网站生成器,可以帮助你创建快速、高性能的网站。以下是Hugo框架的安装教程,详细解释如何在不同操作系统上安装Hugo。

注意:在安装Hugo之前,请确保你已经安装了Git和一个文本编辑器(如VSCode、Sublime Text等),这些工具在创建和管理Hugo网站时非常有用。

在 macOS 上安装 Hugo

  1. 打开终端应用。

  2. 使用Homebrew安装Hugo。如果你没有安装Homebrew,请首先安装它。

    1
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
  3. 安装Hugo。

    1
    brew install hugo
  4. 验证安装。

    1
    hugo version

在 Windows 上安装 Hugo

  1. 下载Hugo的Windows二进制文件(.exe):https://github.com/gohugoio/hugo/releases

  2. 解压下载的ZIP文件,将hugo.exe文件移动到一个你可以轻松访问的目录。你可以将它放在C:\Hugo或其他自定义目录中。

  3. 添加Hugo的可执行文件路径到系统环境变量:

    • 在Windows搜索框中,输入”环境变量”,并选择”编辑系统环境变量”。
    • 在”系统属性”窗口中,点击”高级”选项卡,然后点击”环境变量”按钮。
    • 在”系统变量”部分,找到”Path”,并点击”编辑”。
    • 在”编辑环境变量”窗口中,点击”新建”,并添加Hugo的可执行文件路径,比如C:\Hugo
    • 点击”确定”,保存更改。
  4. 验证安装。

    打开命令提示符(CMD)或PowerShell,并运行:

    1
    hugo version

在 Linux 上安装 Hugo

在大多数Linux发行版中,你可以使用包管理器来安装Hugo。以下是一些示例:

使用 apt-get(Debian/Ubuntu)

1
2
sudo apt-get update
sudo apt-get install hugo

使用 yum(CentOS/RHEL)

1
2
sudo yum install epel-release
sudo yum install hugo

使用 pacman(Arch Linux)

1
sudo pacman -S hugo

使用 snap(通用Linux)

如果你的发行版支持Snap包,你可以使用Snap来安装Hugo。

1
sudo snap install hugo

从源代码编译

如果没有包管理器支持或你想要编译Hugo的最新版本,你可以从源代码编译Hugo。请参考Hugo的官方文档以获取更多信息:https://gohugo.io/getting-started/installing/#source

验证安装

无论你使用哪种操作系统,安装完成后,你可以打开终端或命令行界面并运行以下命令来验证Hugo是否正确安装:

1
hugo version

如果Hugo已成功安装,它将显示版本信息。

一旦你成功安装了Hugo,你就可以开始使用它来创建和管理静态网站。你可以按照前面提到的示例或Hugo的官方文档来创建自己的网站。