Python使用base64模块进行二进制数据编码详解

前言

昨天团队的学妹来问关于POP3协议的问题,所以今天稍稍研究了下POP3协议的格式和Python里面的poplib。而POP服务器往回传的数据里有一部分需要用到Base64进行解码,所以就顺便看了下Python里面的base64模块。

本篇先讲一下base64模块,该模块提供了关于Base16,Base32,Base64,Base85和Ascii85的编码和解码相关的函数。有关poplib模块的内容,会在后面发上来。嗯,又挖了一个坑,这辈子挖的坑填不完了...

以下内容摘自http://bbs.chinaunix.net/thread-1150250-1-1.html,详细说明了为什么回传的数据会先经过Base64编码:

由於歷史原因,Internet上有些郵件系統只支援7Bit的字元傳輸,而漢字的內碼是8Bit的,當在電子郵件中發送中文時,如果經過這些只支援7Bit字元的郵件系統,便會將漢字內碼的第八位元的1全部變成0。
以”中文”兩字為例,HEX為A4A4A4E5,當最高位元被清掉時就會變成24242465,也就是”$$$e”。telnet也存在這樣子的問題。

除了中文郵件外,使用電子郵件傳送圖片、程式、壓縮文件等也會發生這個問題。所以在電子郵件中一般採用各種郵件編碼方式來解決這個問題,將8Bit按照一定的規則進行編碼,便可以完好地通過只支持7Bit字元的郵件系統。

常見的郵件編碼有UU與MIME,而MIME(Multipurpose Internet Mail Extentions)一般翻譯成「多媒體傳送模式」,顧名思義,它標榜的就是可以傳送多媒體型式的檔案,可以在一封mail中附加各種型式檔案一起送出。

MIME定義兩種編碼方法:Base64與QP(Quote-Printable),兩者使用時機不同,QP的規則是對於資料中的7bits無須重複encode,僅8bits資料轉成7bits。QP編碼適用於非US-ASCII的文字內容,例如我們的中文檔案,而Base64的編碼規則,是將整個檔案重新編碼,編成7bits,它是用於傳送binary檔案時使用。由於編碼的方式不同,會影響編碼之後的檔案大小。有些較懶惰的軟體便都一律採用Base64編碼了。

Base64

base64模块提供了6个函数用于Base64的编码和解码,可以将他们分为三组。

base64.b64encode(s, altchars=None)
base64.b64decode(s, altchars=None, validate=False)

参数s代表需要编码/解码的数据。其中b64encode的参数s的类型必须是字节包(bytes)。b64decode的参数s可以是字节包(bytes),也可以是字符串(str)。

由于Base64编码后的数据中可能会含有'+'或者'/'两个符号,如果编码后的数据用于url或者文件系统的路径中,就可能会导致Bug。所以base64模块提供了将编码后的数据中'+'和'/'进行替换的方法。

参数altchars必须是长度为2的字节包,这两个符号会用于替换编码后数据中的'+'和'/'。这个参数默认是None。

参数validate默认为False。如果它为True时,base64模块在进行解码前会先检查s中是否有非base64字母表中的字符,如果有的话则抛出错误binascii.Error: Non-base64 digit found。

如果数据的长度不正确则会抛出错误binascii.Error: Incorrect padding。

>>> import base64
>>> x = base64.b64encode(b'test')
>>> x
b'dGVzdA=='
>>> base64.b64decode(x)
b'test'

base64.standard_b64encode(s)
base64.standard_b64decode(s)

这组函数会直接将参数s传到上一组函数中。

base64.urlsafe_b64encode(s)
base64.urlsafe_b64decode(s)

这组函数同样基于第一组函数,但进行编码后会将输出数据中的'+'和'/'替换为'-‘和'_'。解码前则将数据中的'-‘和'_'替换为'+'和'/'。

另,Base64编码还会产生一个符号'=',这个符号用于将数据长度填充到4的倍数。

Base32

base64.b32encode(s)
base64.b32decode(s, casefold=False, map01=None)

参数s与Base64一致。

Base32编码后的字符范围为[2-7A-Z],是不支持小写字母的。不过当参数casefold为True时,Base32解码时可以接受小写字母的输入。但是为了安全考虑,这个参数默认为False。

Base32的解码同时还允许将数字0替换为大写字母O,把数字1替换为大写字母I或者L。参数map01可以指定将数字1替换为哪个字符(源码中并没有限定必须是字母I或者L其中之一),当这个参数非None时,数字0总是会被替换为字母O。同样为了安全考虑,这个参数默认为None。

Base16

base64.b16encode(s)
base64.b16decode(s, casefold=False)

Base16编码后的字符范围为[0-9A-F]。

参数s和casefold的作用与Base32一致。

Base85

base64.b85encode(b, pad=False)
base64.b85decode(b)

参数b为用于编码/解码的数据,类型要求跟Base64的参数s一致。

参数pad为True时,在编码前会用b'\0'将数据填充到长度为4的倍数。不过在解码的时候不会移除这些填充数据。

这组函数是在Python3.4之后新增的。

Ascii85

base64.a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False)

参数b为用于编码的数据,类型必须为bytes。

参数foldspaces为True时会用b'y'来表示4个连续的空格。

参数wrapcol为一个整数,当wrapcol非0时,这个整数控制编码后的输出每多少个字符添加一个换行符b'\n'。

参数pad为True时,数据在编码前会用b'\0'填充到长度为4的倍数。解码的时候不会移除这些填充数据。

参数adobe指定了数据是否采用Adobe的格式。Adobe Ascii85的编码数据由<\~和\~>包围起来,如果这个参数为True,返回的数据会加上这对符号。

base64.a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v')

参数b为用于编码的数据,类型可以为bytes或者str。

参数foldspaces为True时会用b'y'来表示4个连续的空格。

参数adobe指定了数据是否采用Adobe的格式。Adobe Ascii85的编码数据由<\~和\~>包围起来,如果这个参数为True,解码前base64会先去掉这对符号。

参数ignorechars指定了解码时需要忽略掉的字符。默认包含了ASCII中所有的空白符。

这组函数是在Python3.4之后新增的。

base64模块的官方文档中提到:Base85和Ascii85使用5个字符编码4个字节,而Base64使用6个字符编码4个字节(实际上是4个字符编码3个字节),当空间不充裕时前两者会比Base64更高效。

旧API

base64仍然保留了一部分旧的API,用于一些特殊用途。

base64.encode(input, output)
base64.decode(input, output)

这组函数使用二进制文件作为数据源,并将编码/解码后的数据写入二进制文件。

base64.encodebytes(s)
base64.decodebytes(s)

encodebytes和b64encode在内部都是调用的binascii模块的b2a_base64,只不过encodebytes调用b2a_base64时newline参数使用默认值True。也就是说,encodebytes在输出数据的时候,每76个字节会添加一个换行符b'\n'。

decodebytes和默认参数下的b64decode基本一致。只有参数类型的检查不一样,decodebytes只支持bytes类型的数据。

base64.encodestring(s)
base64.decodestring(s)

这组函数在Python3.1之后就废弃了,目前会直接调用上一组函数。

总结

base64模块提供了对二进制数据进行编码的接口,其中包括了标准的Base64,Base32,Base16和事实标准Ascii85和Base85。通过学习这个模块,顺便学习了一下二进制数据编码的各种细节,感受颇深。有时候我们自以为了解计算机,了解互联网,其实每个人看到的都只是沧海一粟,不值一提。这个领域对于我来说还有很多未知,是等待探索的,而我也不会停止探索的脚步。

以上就是本文关于Python使用base64模块进行二进制数据编码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

您可能感兴趣的文章:

  • Python基础之getpass模块详细介绍
  • Python用sndhdr模块识别音频格式详解
  • Python用imghdr模块识别图片格式实例解析
  • 简单了解python模块概念
  • Python编程pygame模块实现移动的小车示例代码
  • python的numpy模块安装不成功简单解决方法总结
  • python Crypto模块的安装与使用方法
  • Python内置模块turtle绘图详解
  • Python中getpass模块无回显输入源码解析
时间: 2018-01-08

Python中getpass模块无回显输入源码解析

本文主要讨论了python中getpass模块的相关内容,具体如下. getpass模块 昨天跟学弟吹牛b安利Python标准库官方文档的时候偶然发现了这个模块.仔细一看内容挺少的,只有两个主要api,就花了点时间阅读了一下源码,感觉挺实用的,在这安利给大家. getpass.getpass(prompt='Password: ', stream=None) 调用该函数可以在命令行窗口里面无回显输入密码.参数prompt代表提示字符串,默认是'Password: '.在Unix系统中,strea

Python内置模块turtle绘图详解

urtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x.纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行的路径上绘制了图形. turtle绘图的基础知识: 1.画布(canvas) 画布就是turtle为我们展开用于绘图区域,我们可以设置它的大小和初始位置. 设置画布大小 turtle.screensize(canvwidth=None,canvheight=None,bg=None),参数分别为画布的

python Crypto模块的安装与使用方法

前言 最开始想尝试在windows下面安装python3.6,虽然python安装成功,但在安装Cryto模块用pip3 install pycrypto老是会报错.老夫搞了半天,最终决定在linux下面去做. 以下流程限于linux系统: Crypto不是自带的模块,需要下载.http://www.voidspace.org.uk/python/modules.shtml#pycrypto 我下载了之后,发现下载的是crypto而不是Crypto(就是差个首字母大小写) 而crypto.Cip

Python基础之getpass模块详细介绍

本文主要给大家介绍了关于Python中getpass模块的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍: getpass模块提供了平台无关的在命令行下输入密码的方法; 该模块主要提供: 两个函数: getuser, getpass 一个报警: GetPassWarning(当输入的密码可能会显示的时候抛出,该报警为UserWarning的一个子类) 备注: 上面为密码显示时抛出的报警 getpass.getuser() 该函数返回登陆的用户名,不需要参数 该函数会检查环境变

Python用sndhdr模块识别音频格式详解

本文主要介绍了Python编程中,用sndhdr模块识别音频格式的相关内容,具体如下. sndhdr模块 功能描述:sndhdr模块提供检测音频类型的接口. 唯一一个API sndhdr模块提供了sndhdr.what(filename)和sndhdr.whathdr(filename)两个函数.但实际上它们的功能是一样的.(不知道多写一个的意义何在,what函数在内部调用了whathdr函数并把数据完完整整地返回) 在之前的版本,whathdr函数返回元组类型的数据,在Python3.5版本之

Python用imghdr模块识别图片格式实例解析

imghdr模块 功能描述:imghdr模块用于识别图片的格式.它通过检测文件的前几个字节,从而判断图片的格式. 唯一一个API imghdr.what(file, h=None) 第一个参数file可以是用rb模式打开的file对象或者表示路径的字符串和PathLike对象.h参数是一段字节串.函数返回表示图片格式的字符串. >>> import imghdr >>> imghdr.what('test.jpg') 'jpeg' 具体的返回值和描述如下: 返回值 描述

简单了解python模块概念

本文主要讲述的是Python中的模块的概念,具体如下. 模块是python组织代码的基本方式: python的脚本都是用扩展名为py的文本文件保存的. 一个脚本可以单独运行,也可以导入另一个脚本中运行. 当脚本被导入另一个脚本中运行时,我们将其称为模块. 模块名与脚本文件名相同: 比如你有一个items.py脚本, 则可以在另外一个脚本中用import items语句导入它 这是一段名字叫cal.py的python代码,它将被作为cal模块导入的后面的代码中: #!/usr/bin/python

python的numpy模块安装不成功简单解决方法总结

为了画个图,被numpy这个模块的安装真的折腾疯了!!!一直装不上,花了几个小时,看了网上的很多教程.方法发现总结得不是很全,这里总结一下,防止大家再出现这个问题没有解决方法. Python的魅力之一,就是拥有众多功能强大的插件,但是这些插件的寻找.安装.升级在windows系统上却非常之麻烦.首先安装完Python后需要在系统配置环境变量,接下来又要安装Setuptools,而且安装过程中还会报编码错误,对于需要拷贝源码安装的还需要去CMD里打命令,还得小心翼翼避免打错参数,如果没有一位有经验

Python编程pygame模块实现移动的小车示例代码

Pygame是跨平台Python模块,专为电子游戏设计,包含图像.声音.建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚. 最近一个星期学习了一下python的pygame模块,顺便做个小程序巩固所学的,运行效果如下: 其中,背景图"highway.jpg"是使用PhotoShop将其分辨率改变为640 × 480,而小车"car.png"则是将其转变为png格式的图片,并且填充其背景色,让其拥有透明性. 代码测试可用: # -*

Python使用pickle模块存储数据报错解决示例代码

本文研究的主要是Python使用pickle模块存储数据报错解决方法,以代码的形式展示,具体如下. 首先来了解下pickle模块 pickle提供了一个简单的持久化功能.可以将对象以文件的形式存放在磁盘上. pickle模块只能在python中使用,python中几乎所有的数据类型(列表,字典,集合,类等)都可以用pickle来序列化, pickle序列化后的数据,可读性差,人一般无法识别. 接下来我们看下Python使用pickle模块存储数据报错解决方法. 代码: # 写入错误 TypeEr

python使用OpenCV模块实现图像的融合示例代码

可以通过OpenCV函数cv.add()或简单地通过numpy操作添加两个图像,res = img1 + img2.两个图像应该具有相同的深度和类型,或者第二个图像可以是标量值. 三种融合 注意融合时,一般来说两个图像的尺寸是一样大小的,如果大小不一样,需要把大的图像的某一部分先截出来,与小的图先融合,再作为整体替换掉原来大图中抠出的小图部分. """ # @Time : 2020/4/3 # @Author : JMChen """ impor

Python基于pygame模块播放MP3的方法示例

本文实例讲述了Python基于pygame模块播放MP3的方法.分享给大家供大家参考,具体如下: 安装pygame(可参考:安装Python和pygame及相应的环境变量配置) pip安装这个whl文件 装完就直接跑代码啦,很短的 import time import pygame file=r'C:\Users\chan\Desktop\Adele - All I Ask.mp3' pygame.mixer.init() print("播放音乐1") track = pygame.m

python中pygame模块用法实例

本文实例讲述了python中pygame模块用法,分享给大家供大家参考.具体方法如下: import pygame, sys from pygame.locals import * #set up pygame pygame.init() windowSurface = pygame.display.set_mode((500, 400), 0, 32) pygame.display.set_caption("hello, world") BLACK = (0, 0, 0) WHITE

python使用PyGame模块播放声音的方法

本文实例讲述了python使用PyGame模块播放声音的方法.分享给大家供大家参考.具体实现方法如下: import pygame pygame.init() pygame.mixer.music.load("sound_file.ogg") pygame.mixer.music.play() pygame.event.wait() 希望本文所述对大家的Python程序设计有所帮助.

基于python中pygame模块的Linux下安装过程(详解)

一.使用pip安装Python包 大多数较新的Python版本都自带pip,因此首先可检查系统是否已经安装了pip.在Python3中,pip有时被称为pip3. 1.在Linux和OS X系统中检查是否安装了pip 打开一个终端窗口,并执行如下命令: Python2.7中: zhuzhu@zhuzhu-K53SJ:~$ pip --version pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7) Python3.X中: z

python编程测试电脑开启最大线程数实例代码

本文实例代码主要实现python编程测试电脑开启最大线程数,具体实现代码如下. #!/usr/bin/env python #coding=gbk import threading import time, random, sys class Counter: def __init__(self): self.lock = threading.Lock() self.value = 0 def increment(self): self.lock.acquire() self.value = v

python的paramiko模块实现远程控制和传输示例

本文介绍了python的paramiko模块实现远程控制和传输示例,分享给大家,具体如下: 1 安装 sudo pip install paramiko 2 ssh实现远程控制 #LINUX下执行shell ssh username@ip #输入密码后就可以对远程机器进行操作 ssh username@ip command #输入密码后远程机器就执行command ssh运行后,想退出,可以kill掉ssh进程. 3 paramiko实现ssh import paramiko hostname

python编程实现随机生成多个椭圆实例代码

椭圆演示: 代码示例: import matplotlib.pyplot as plt import numpy as np from matplotlib.patches import Ellipse NUM = 250 ells = [Ellipse(xy=np.random.rand(2) * 10, width=np.random.rand(), height=np.random.rand(), angle=np.random.rand() * 360) for i in range(N