目录
bytes函数在Python中提供了一种不可变字节序列的表示方式,这在实际编程中有多种应用场景。常见的应用场景有:
1、二进制数据处理:当需要处理二进制数据时,bytes()是一个很好的选择。你可以使用它来存储和操作二进制数据,例如,读取或写入文件、网络通信中的数据包等。
2、网络编程:在网络编程中,经常需要将数据发送为字节对象。例如,可以使用socket模块将字节对象发送到远程服务器。
3、图像和音视频处理:当处理图像或音视频文件时,通常需要将文件读取为字节对象。然后可以使用各种库(如PIL)处理字节对象。
4、存储和序列化数据:当存储或序列化数据时,可以使用bytes()函数将数据转换为字节对象。然后可以将字节对象写入文件或将其作为消息传递到另一个进程。
5、加密与解密:在加密和解密算法中,字节操作是常见的。bytes()函数可以将字符串或其他数据类型转换为字节对象,以便进行加密或解密操作。
6、处理二进制协议:某些协议(例如,MQTT、WebSocket等)要求使用二进制格式进行通信。在这些情况下,我们需要使用bytes()来构建和解析消息。
总之,在Python中,bytes()函数在许多涉及处理二进制数据的场景中都很有用。
1、bytes函数:
1-1、Python:
- # 1.函数:bytes
- # 2.功能:用于处理不可变字节序列,即创建不可修改的字节数组
- # 3.语法:bytes(source, encoding, errors)
- # 4.参数:
- # 4-1、source>>>
- # 1、整数,包括正整数、0和负整数
- # 2、字符串
- # 3、可迭代对象,包括但不限于以下类型:
- # 3-1、序列类型:
- # list(列表):有序的元素集合
- # tuple(元组):不可变的有序的元素集合
- # str(字符串):字符的有序集合
- # bytes(字节序列):字节的有序集合
- # bytearray(可变字节序列):可变的字节的有序集合
- # range(范围对象):表示一个不可变的整数序列
- # memoryview(内存视图):用于在不需要复制数据的情况下访问对象的内存
- # 3-2、集合类型:
- # set(集合):无序且不包含重复元素的集合
- # frozenset(冻结集合):不可变的无序且不包含重复元素的集合
- # 3-3、字典与字典视图:
- # dict(字典):无序的键值对集合
- # dict的keys()、values()、items()方法返回的视图对象
- # 3-4、文件对象:
- # 打开的文件对象也是可迭代的,可以通过迭代逐行读取文件内容
- # 3-5、自定义可迭代对象:
- # 任何定义了__iter__()方法的对象都可以被视为可迭代对象。这个方法应该返回一个迭代器对象
- # 3-6、生成器:
- # 生成器函数和生成器表达式创建的生成器对象也是可迭代的
- # 3-7、其他内置类型:
- # 某些内置的数据类型或函数返回的对象也可能是可迭代的,比如map、filter、zip等函数返回的对象
- # 4-2、encoding>>>表示进行转换时采用的字符编码,默认为UTF-8编码
- # 4-3、errors>>>表示错误处理方式(报错级别),常见的报错级别有:
- # 1、strict:严格级别(默认级别),字符编码有报错时即抛出异常
- # 2、ignore:忽略级别,字符编码有报错,忽略掉
- # 3、replace:替换级别,字符编码有报错,替换成符号“?”
- # 5.返回值:返回一个新的不可变字节数组(若3个参数均未提供,则返回长度为0的字节数组)
- # 6.说明:
- # 6-1、如果参数source为字符串,那么参数encoding也必须提供,否则将提示TypeError错误。详情如下:
- # TypeError: string argument without an encoding
- # print(bytes("myelsa"))
- # 6-2、如果参数source为可迭代对象,那么可迭代对象的元素必须为0-255的范围内的整数,否则将抛出异常。详情如下:
- # ValueError: byte must be in range(0, 256)
- # print(bytes([1024, 8, 6]))
- # TypeError: 'float' object cannot be interpreted as an integer
- # print(bytes([3.14, 1.5, 6.0]))
- # 6-3、bytearray()函数与bytes()函数的主要区别:前者产生的对象元素可以修改,而后者不能修改
- # 6-4、如果参数source为符合缓冲区接口的对象,则将使用只读方式将字节读取到字节数组后返回
- # 7.示例:
- # 应用1:二进制数据处理
- # 创建一个字节对象
- binary_data = bytes([0x01, 0x02, 0x03, 0x04])
- print("原始二进制数据:", binary_data)
- # 转换整数为字节
- integer_value = 12345
- # 将整数转换为4字节长度的bytes对象(大端字节序)
- integer_bytes = integer_value.to_bytes(4, byteorder='big')
- print("整数转换的二进制数据:", integer_bytes)
- # 将字符串转换为字节(编码为UTF-8)
- text = "Hello, Python!"
- text_bytes = text.encode('utf-8')
- print("字符串转换的二进制数据:", text_bytes)
- # 将字节对象解码回字符串
- decoded_text = text_bytes.decode('utf-8')
- print("解码后的字符串:", decoded_text)
- # 使用bytes函数和列表推导式创建一个特定模式的字节序列
- pattern_bytes = bytes([i % 256 for i in range(10)])
- print("模式二进制数据:", pattern_bytes)
- # 将bytes对象转换为十六进制表示
- hex_string = pattern_bytes.hex()
- print("十六进制表示:", hex_string)
- # 将十六进制字符串转换回bytes对象
- back_to_bytes = bytes.fromhex(hex_string)
- print("转换回bytes对象:", back_to_bytes)
- # 切片和连接bytes对象
- first_half = binary_data[:2]
- second_half = binary_data[2:]
- concatenated = first_half + second_half
- print("切片和连接后的数据:", concatenated)
- # 遍历bytes对象
- for byte in binary_data:
- print(f"字节值: {byte}")
- # 原始二进制数据: b'\x01\x02\x03\x04'
- # 整数转换的二进制数据: b'\x00\x0009'
- # 字符串转换的二进制数据: b'Hello, Python!'
- # 解码后的字符串: Hello, Python!
- # 模式二进制数据: b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'
- # 十六进制表示: 00010203040506070809
- # 转换回bytes对象: b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'
- # 切片和连接后的数据: b'\x01\x02\x03\x04'
- # 字节值: 1
- # 字节值: 2
- # 字节值: 3
- # 字节值: 4
-
- # 应用2:网络编程
- import socket
- # 服务器端代码
- # 创建 TCP/IP 套接字
- server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 获取本地主机名
- host = socket.gethostname()
- # 设置端口号
- port = 12345
- # 绑定端口号
- server_socket.bind((host, port))
- # 设置最大连接数,超过后排队
- server_socket.listen(5)
- while True:
- # 建立客户端连接
- client_socket, addr = server_socket.accept()
- print(f"连接地址: {addr}")
- # 接收 1024 字节的数据
- data = client_socket.recv(1024)
- # 打印接收到的数据
- print(f"接收到的数据: {data.decode('utf-8')}")
- # 发送响应数据
- response = "已收到消息".encode('utf-8')
- client_socket.sendall(response)
- # 关闭连接
- client_socket.close()
- # 客户端代码
- # 创建 TCP/IP 套接字
- client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 设置服务器地址和端口号
- server_address = ('localhost', 12345)
- # 连接到服务器
- client_socket.connect(server_address)
- # 发送数据
- message = "你好,服务器!".encode('utf-8')
- client_socket.sendall(message)
- # 接收服务器响应
- data = client_socket.recv(1024)
- # 打印接收到的响应
- print(f"接收到的响应: {data.decode('utf-8')}")
- # 关闭连接
- client_socket.close()
-
- # 应用3:图像和音视频处理(注意:运行此程序,需要确保已经安装了pillow库)
- import os
- from PIL import Image
- def read_image_as_bytes(image_path):
- with open(image_path, 'rb') as file:
- image_bytes = file.read()
- return image_bytes
- # 读取图像并显示
- def display_image(image_path):
- image = Image.open(image_path)
- image.show()
- # 假设你有一个处理 bytes 对象的函数
- def process_image_bytes(image_bytes):
- # 这里应该是对 bytes 对象的实际处理逻辑
- # 例如,你可以将 bytes 对象发送到另一个函数或通过网络发送
- # 但为了示例,我们只是打印其长度
- print(f"Received {len(image_bytes)} bytes of image data.")
- # ... 实际处理代码 ...
- if __name__ == '__main__':
- # 图像文件路径
- image_path = 'input.jpg'
- # 确保文件存在
- if os.path.exists(image_path):
- # 读取图像为 bytes 对象
- image_data = read_image_as_bytes(image_path)
- display_image(image_path)
- # 处理 bytes 对象
- process_image_bytes(image_data)
- else:
- print(f"File {image_path} does not exist.")
- # Received 151245 bytes of image data.
- # 显示图像文件
-
- # 应用4:存储和序列化数据
- import pickle
- # 定义一个简单的数据结构
- data = {
- 'name': 'Myelsa',
- 'age': 42,
- 'city': 'Guangzhou'
- }
- # 序列化数据为bytes对象
- serialized_data = pickle.dumps(data)
- print(f"序列化后的bytes对象: {serialized_data}")
- # 反序列化bytes对象为原始数据结构
- deserialized_data = pickle.loads(serialized_data)
- print(f"反序列化后的数据: {deserialized_data}")
- # 验证反序列化后的数据是否与原始数据相同
- assert data == deserialized_data, "数据不一致"
- print("数据验证成功!")
- # 序列化后的bytes对象: b'\x80\x04\x950\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x06Myelsa\x94\x8c\x03age\x94K*\x8c\x04city\x94\x8c\tGuangzhou\x94u.'
- # 反序列化后的数据: {'name': 'Myelsa', 'age': 42, 'city': 'Guangzhou'}
- # 数据验证成功!
-
- # 应用5:加密与解密
- from cryptography.hazmat.backends import default_backend
- from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
- from cryptography.hazmat.primitives import padding
- from base64 import b64encode, b64decode
- # 生成一个随机的AES密钥,长度通常为16、24或32字节
- key = b'Sixteen byte key'
- # 初始化一个填充器对象,用于在加密前填充数据,并在解密后去除填充
- padder = padding.PKCS7(128).padder()
- unpadder = padding.PKCS7(128).unpadder()
- def encrypt_data(data: bytes, key: bytes) -> bytes:
- # 填充数据
- padded_data = padder.update(data) + padder.finalize()
- # 创建一个Cipher对象
- cipher = Cipher(algorithms.AES(key), modes.CBC(b'\x00' * 16), backend=default_backend())
- # 创建一个加密器对象
- encryptor = cipher.encryptor()
- # 加密数据
- ciphertext = encryptor.update(padded_data) + encryptor.finalize()
- # 为了便于存储或传输,可以将bytes对象转换为base64编码的字符串
- return b64encode(ciphertext)
- def decrypt_data(ciphertext: bytes, key: bytes) -> bytes:
- # 如果ciphertext是base64编码的字符串,先解码为bytes对象
- ciphertext = b64decode(ciphertext)
- # 创建一个Cipher对象
- cipher = Cipher(algorithms.AES(key), modes.CBC(b'\x00' * 16), backend=default_backend())
- # 创建一个解密器对象
- decryptor = cipher.decryptor()
- # 解密数据
- decrypted_padded_data = decryptor.update(ciphertext) + decryptor.finalize()
- # 去除填充
- decrypted_data = unpadder.update(decrypted_padded_data) + unpadder.finalize()
- return decrypted_data
- if __name__ == '__main__':
- # 明文消息,必须是bytes类型
- plain_text = b'I love python!'
- # 加密数据
- encrypted_text = encrypt_data(plain_text, key)
- print(f"Encrypted text: {encrypted_text}")
- # 解密数据
- decrypted_text = decrypt_data(encrypted_text, key)
- print(f"Decrypted text: {decrypted_text}")
- # 验证解密后的数据是否与原始数据相同
- assert plain_text == decrypted_text, "加密和解密后数据不一致!"
- print("数据验证成功!")
- # Encrypted text: b'AiDb6dB5orehw8J1bzeX8Q=='
- # Decrypted text: b'I love python!'
- # 数据验证成功!
-
- # 应用6:处理二进制协议
- import struct
- def encode_binary_protocol(data: bytes) -> bytes:
- # 计算数据的长度
- length = len(data)
- # 使用struct模块将长度编码为两个字节(大端序)
- length_bytes = struct.pack('>H', length)
- # 将长度和数据拼接起来形成完整的协议数据包
- protocol_packet = length_bytes + data
- return protocol_packet
- def decode_binary_protocol(protocol_packet: bytes) -> bytes:
- # 从协议数据包中提取前两个字节作为长度
- length_bytes = protocol_packet[:2]
- # 使用struct模块解码长度
- length = struct.unpack('>H', length_bytes)[0]
- # 检查数据包长度是否匹配实际长度
- if length != len(protocol_packet) - 2:
- raise ValueError("Protocol packet length does not match the encoded length")
- # 提取数据部分
- data = protocol_packet[2:]
- # 返回数据部分
- return data
- if __name__ == '__main__':
- # 明文消息,必须是bytes类型
- original_data = b'Hello, python!'
- encoded_data = encode_binary_protocol(original_data)
- print(f"Encoded data: {encoded_data}")
- decoded_data = decode_binary_protocol(encoded_data)
- print(f"Decoded data: {decoded_data}")
- # 验证数据是否一致
- assert original_data == decoded_data, "编码和解码后的数据不一致!"
- print("数据验证成功!")
- # Encoded data: b'\x00\x0eHello, python!'
- # Decoded data: b'Hello, python!'
- # 数据验证成功!
1-2、VBA:
VBA很难模拟类似场景,略。
2、相关文章:
2-2、Python-VBA函数之旅-bytearray()函数
2-3、Python-VBA函数之旅-callable()函数
Python算法之旅:Algorithm
Python函数之旅:Function
个人主页:非风V非雨-CSDN博客
欢迎志同道合者一起交流学习,我的QQ:94509325/微信:

遨游码海,我心飞扬
微信名片


评论记录:
回复评论: